Как Разрешить тип на основе значения конфигурации конечного пользователя?

У меня есть интерфейс (назовите его IAcmeService), который имеет несколько реализаций.

FileSystemAcmeService
DatabaseAcmeService
NetworkAcmeService

Конечный пользователь должен быть в состоянии выбрать, какая реализация будет использоваться и также сохранит тот выбор.

В настоящее время я настраиваю свой контейнер IOC (Единица) для регистрации всего известного implemenatation в имени.

container.RegisterType(of IAcmeService, FileSystemAcmeService)("FileSystemAcmeService")
container.RegisterType(of IAcmeService, DatabaseAcmeService)("DatabaseAcmeService")
container.RegisterType(of IAcmeService, NetworkAcmeService)("NetworkAcmeService")

Чтобы позволить пользователю сохранять их выбор, у меня есть app.config файл раздела конфигурации, который хранит выбранное сервисное название к использованию.

Для разрешения выбранной реализации, я выполняю в ручной Твердости Инициализировать метод класса использование сервис.

Private _service as IAcmeService
Public Sub Initialize()
    _service = container.Resolve(of IAcmeService)(_config.AcmeServiceName)
End Sub

Это не кажется правильным, потому что мой класс должен знать о контейнере. Но я не могу выяснить иначе.

Там другие пути состоят в том, чтобы позволить выбор конечного пользователя без класса, знающего о контейнере?

10
задан Rick 1 February 2010 в 21:41
поделиться

1 ответ

Определение и реализация и Абстрактная фабрика - это стандартное решение этого типа проблемы. Если вы простите мое использование C #, вы можете определить интерфейс IacmeserviceFactoractoractoractoractory, такой как это:

public interface IAcmeServiceFactory
{
    IAcmeService Create(string serviceName);
}

Теперь вы можете написать конкретное внедрение, подобное этому:

public class AcmeServiceFactory : IAcmeServiceFactory
{
    private readonly IAcmeService fsService;
    private readonly IAcmeService dbService;
    private readonly IAcmeService nwService;

    public AcmeServiceFactory(IAcmeService fsService,
        IAcmeService dbService, IAcmeService nwService)
    {
        if (fsService == null)
        {
            throw new ArgumentNullException("fsService");
        }
        if (dbService == null)
        {
            throw new ArgumentNullException("dbService");
        }
        if (nwService == null)
        {
            throw new ArgumentNullException("nwService");
        }

        this.fsService = fsService;
        this.dbService = dbService;
        this.nwService = nwService;
    }

    public IAcmeService Create(string serviceName)
    {
        switch case serviceName
        {
            case "fs":
                return this.fsService;
            case "db":
                return this.dbService;
            case "nw":
                return this.nwService;
            case default:
                throw new ArgumentException("serviceName");
        }
    } 
}

Вы можете сделать его более общего назначения, если вы хотите быть в состоянии Создайте произвольное количество экземпляров IacMeservice, но я оставлю это как упражнение для читателя :)

Это потребует также зарегистрировать завод с единством. В любом месте, где вам нужен Iacmeservice на основе имени, вы принимаете зависимость от IacmeserviceFactory вместо самого IacMeservice.

9
ответ дан 4 December 2019 в 01:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: