Внедрение зависимостей WCF и аннотация factory

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

Profile GetProfileInfo(string profileType, string profileName)

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

если profileType является "A", прочитанным из базы данных.

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

Возникает вопрос: как реализовать его с помощью контейнера инъекций зависимостей?

Ответ 1

Предположим сначала, что у вас есть IProfileRepository примерно так:

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

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

Вы можете сделать это, представив этот Абстрактный 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 по выбору, чтобы связать все это для вас...

Ответ 2

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

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


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

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

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