WCF Зависимость инъекций и абстрактная фабрика - PullRequest
19 голосов
/ 30 января 2010

У меня есть этот метод wcf

Profile GetProfileInfo(string profileType, string profileName)

и бизнес-правило:

, если для profileType задано значение "A" из базы данных.

если profileType - "B", прочитанный из файла XML.

Вопрос в том, как это реализовать, используя контейнер для внедрения зависимостей?

Ответы [ 2 ]

23 голосов
/ 30 января 2010

Давайте сначала предположим, что у вас есть IProfileRepository что-то вроде этого:

public interface IProfileRepository
{
     Profile GetProfile(string profileName);
}

, а также две реализации: DatabaseProfileRepository и XmlProfileRepository. Проблема в том, что вы хотели бы выбрать правильный, основанный на значении profileType.

Вы можете сделать это, представив Abstract Factory :

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, чтобы связать все это для вас ...

4 голосов
/ 08 апреля 2016

Отличный ответ от Марка. Однако данное решение - не Абстрактная фабрика , а реализация шаблона Стандартный Фабрика Пожалуйста, проверьте, как классы Marks вписываются в UML-диаграмму Standard Factory Pattern. Нажмите здесь, чтобы увидеть классы выше, примененные к шаблону Factory UML

Поскольку в шаблоне Factory фабрика знает о конкретных классах, мы можем сделать код ProfileRepositoryFactory намного проще, как показано ниже. Проблема с внедрением различных репозиториев в фабрику состоит в том, что у вас больше изменений кода каждый раз, когда вы добавляете новый конкретный тип. С приведенным ниже кодом вам нужно только обновить коммутатор, чтобы включить новый конкретный класс


    public class ProfileRepositoryFactory : IProfileRepositoryFactory
    {
        public IProfileRepository Create(string profileType)
        {
            switch(profileType)
            {
                case "A":
                    return new DatabaseProfileRepository(); 

                case  "B":
                    return new XmlProfileRepository();
            }
        }
    }

Абстрактная фабрика - это более продвинутый шаблон, используемый для создания семейств связанных или зависимых объектов без указания их конкретных классов. Диаграмма классов UML доступна здесь это хорошо объясняет.

...