WCF Зависимость инъекций и абстрактная фабрика
У меня есть этот метод wcf
Profile GetProfileInfo(string profileType, string profileName)
и бизнес-правило:
если profileType "A" читается из базы данных.
если profileType - "B", читается из XML-файла.
Вопрос в том, как это реализовать с помощью контейнера внедрения зависимостей?
2 ответа
Давайте сначала предположим, что у вас есть IProfileRepository что-то вроде этого:
public interface IProfileRepository
{
Profile GetProfile(string profileName);
}
а также две реализации: DatabaseProfileRepository
а также XmlProfileRepository
, Проблема в том, что вы хотели бы выбрать правильный, основанный на значении profileType.
Вы можете сделать это, представив эту абстрактную фабрику:
public interface IProfileRepositoryFactory
{
IProfileRepository Create(string profileType);
}
Предполагая, что IProfileRepositoryFactory был внедрен в реализацию службы, теперь вы можете реализовать метод GetProfileInfo следующим образом:
public Profile GetProfileInfo(string profileType, string profileName)
{
return this.factory.Create(profileType).GetProfile(profileName);
}
Конкретная реализация IProfileRepositoryFactory может выглядеть следующим образом:
public class ProfileRepositoryFactory : IProfileRepositoryFactory
{
private readonly IProfileRepository aRepository;
private readonly IProfileRepository bRepository;
public ProfileRepositoryFactory(IProfileRepository aRepository,
IProfileRepository bRepository)
{
if(aRepository == null)
{
throw new ArgumentNullException("aRepository");
}
if(bRepository == null)
{
throw new ArgumentNullException("bRepository");
}
this.aRepository = aRepository;
this.bRepository = bRepository;
}
public IProfileRepository Create(string profileType)
{
if(profileType == "A")
{
return this.aRepository;
}
if(profileType == "B")
{
return this.bRepository;
}
// and so on...
}
}
Теперь вам просто нужно выбрать контейнер DI, чтобы связать все это для вас...
Отличный ответ от Mark, однако данное решение - не абстрактная фабрика, а реализация шаблона стандартной фабрики. Пожалуйста, проверьте, как классы Marks вписываются в UML-диаграмму Standard Factory Pattern. Нажмите здесь, чтобы увидеть выше классы, примененные к UML-шаблону Factory
Так как в шаблоне Factory фабрика знает о конкретных классах, мы можем сделать код ProfileRepositoryFactory
гораздо проще, как показано ниже. Проблема с внедрением различных репозиториев в фабрику состоит в том, что у вас больше изменений кода при каждом добавлении нового конкретного типа. С приведенным ниже кодом вам нужно только обновить переключатель, чтобы включить новый конкретный класс
public class ProfileRepositoryFactory : IProfileRepositoryFactory
{
public IProfileRepository Create(string profileType)
{
switch(profileType)
{
case "A":
return new DatabaseProfileRepository();
case "B":
return new XmlProfileRepository();
}
}
}
Абстрактная фабрика - это более продвинутый шаблон, используемый для создания семейств связанных или зависимых объектов без указания их конкретных классов. Диаграмма классов UML, доступная здесь, объясняет это хорошо.