Как мы все знаем, когда мы выводим класс и используем полиморфизм, кто-то где-то должен знать, какой класс создать. Мы можем использовать фабрики, большой оператор switch, if-else-if и т. Д. Я только что узнал от Bill K, что это называется Dependency Injection.
Мой вопрос: рекомендуется ли использовать отражение и атрибуты в качестве механизма внедрения зависимостей? Таким образом, список динамически заполняется по мере добавления новых типов.
Вот пример . Пожалуйста, не комментируйте, как загрузка изображений может быть сделана другими способами, мы знаем .
Предположим, у нас есть следующий интерфейс IImageFileFormat:
public interface IImageFileFormat
{
string[] SupportedFormats { get; };
Image Load(string fileName);
void Save(Image image, string fileName);
}
Различные классы будут реализовывать этот интерфейс:
[FileFormat]
public class BmpFileFormat : IImageFileFormat { ... }
[FileFormat]
public class JpegFileFormat : IImageFileFormat { ... }
Когда файл должен быть загружен или сохранен, менеджеру необходимо перебрать все известные загрузчики и вызвать Load () / Save () из соответствующего экземпляра в зависимости от их SupportedExtensions.
class ImageLoader
{
public Image Load(string fileName)
{
return FindFormat(fileName).Load(fileName);
}
public void Save(Image image, string fileName)
{
FindFormat(fileName).Save(image, fileName);
}
IImageFileFormat FindFormat(string fileName)
{
string extension = Path.GetExtension(fileName);
return formats.First(f => f.SupportedExtensions.Contains(extension));
}
private List<IImageFileFormat> formats;
}
Полагаю, важным моментом здесь является то, должен ли список доступных загрузчиков (форматов) заполняться вручную или с использованием отражения.
От руки:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
formats.Add(new BmpFileFormat());
formats.Add(new JpegFileFormat());
}
По отражению:
public ImageLoader()
{
formats = new List<IImageFileFormat>();
foreach(Type type in Assembly.GetExecutingAssembly().GetTypes())
{
if(type.GetCustomAttributes(typeof(FileFormatAttribute), false).Length > 0)
{
formats.Add(Activator.CreateInstance(type))
}
}
}
Я иногда использую последнее, и мне никогда не приходило в голову, что это может быть очень плохой идеей. Да, добавлять новые классы легко, но механизм регистрации тех же классов труднее понять и, следовательно, поддерживать, чем простой закодированный вручную список.
Пожалуйста, обсудите.