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, доступная здесь, объясняет это хорошо.

Другие вопросы по тегам