Внедрить две конкретные реализации интерфейса в конструктор с помощью простого инжектора - PullRequest
0 голосов
/ 19 мая 2018

у меня и интерфейс IConnector.И есть несколько реализаций, скажем SomeConnector.И мой вариант использования выглядит так:

public class Worker : IWorker
{
    public Worker(IConnector dataConnector, IConnector transactionConnector) {}
}

public class SomeConnector : IConnector
{
    public SomeConnector(IConnectorContext connectorContext) {}
}

В конструкторе Worker мне нужно иметь два экземпляра IConnector.И не только два экземпляра, но два конкретных экземпляра, созданные с их собственным контекстом.Как я могу сделать эту регистрацию?

Обновление1

Добавление ConnectorContext реализация

public class SomeConnectorContext : IConnectorContext
{
    public List<string> Types { get; }
    public int DataTimeoutSeconds { get; }
    public string Key { get; }
    public string ConnectorName { get; }

    public SomeConnectorContext(
        List<string> types, int dataTimeoutSeconds, string key, string connectorName)
    {
        Types = types;
        DataTimeoutSeconds = dataTimeoutSeconds;
        Key = key;
        ConnectorName = connectorName;
    }
}

Обновление2

На самом деле мне нужна какая-то условная регистрация на основе конфига.Например, что-то вроде:

switch (workerType)
{
    // the following code is obviously incorrect, because I
    // don't know how make registrations properly in this case.
    case "worker1":
        //create context for dataConnector based on config.
        Container.Register<IConnectorContext>(new SomeConnectorContext(...));
        //this is dataConnector. and should use dataConnector context.
        Container.Register<IConnector, SomeConnector>();

        //create context for transactionConnector based on config.
        Container.Register<IConnectorContext>(new SomeConnectorContext(...));
        //this is transactionConnector. and should use transactionConnector context.
        Container.Register<IConnector, SomeConnector>();

        Container.Register<IWorker, Worker1>();
        break;

    //in the following case Worker2 needs only one Connector
    case "worker2":
        //create context for allPurposeConnector based on config.
        Container.Register<IConnectorContext>(new SomeConnectorContext(...));
        //this is allPurposeConnector. and should use allPurposeConnector context.
        Container.Register<IConnector, SomeConnector>();

        Container.Register<IWorker, Worker2>();
        break;
}

Update3 Добавление примера назначения workerType.

workerType - это значение конфигурации.Например, его можно установить так: workerType = Properties.Settings.Default.WorkerType;

1 Ответ

0 голосов
/ 28 мая 2018

Я вижу 2 варианта.

Вы можете вручную связать свои зависимости, используя лямбду.Это означает, что вы только регистрируете IWorker и создаете его и его зависимости вручную.Это отключает автоматическое подключение, но в результате получается довольно простой код, как показано в следующем примере:

switch (workerType)
{
    case "worker1":
        var context1 = new SomeConnectorContext(...);
        var context2 = new SomeConnectorContext(...);

        Container.Register<IWorker>(() => Worker1(
            new SomeConnector(context1),
            new SomeConnector(context2)));
        break;

    case "worker2":
        var context1 = new SomeConnectorContext(...);

        Container.Register<IWorker>(() => Worker1(
            new SomeConnector(context1)));
        break;
}

Второй вариант - зарегистрировать SomeConnector в качестве условной регистрации.Это позволяет вам сделать обе SomeConnector регистрации и связать их с соответствующими параметрами конструктора.Это позволяет IWorker быть автоматическим подключением, но приводит к более сложной регистрации, как показано ниже:

switch (workerType)
{
    case "worker1":
        var context1 = new SomeConnectorContext(...);
        Container.RegisterConditional<SomeConnector>(
            Lifestyle.Transient.CreateRegistration(
            () => new SomeConnector(context1), container),
            c => c.Consumer.Target.Name == "dataConnector");

        var context2 = new SomeConnectorContext(...);
        Container.RegisterConditional<SomeConnector>(
            Lifestyle.Transient.CreateRegistration(
            () => new SomeConnector(context2), container),
            c => c.Consumer.Target.Name == "transactionConnector");

        Container.Register<IWorker, Worker1>();
        break;

    case "worker2":
        Container.Register<IConnectorContext>(new SomeConnectorContext(...));
        Container.Register<IConnector, SomeConnector>();
        Container.Register<IWorker, Worker2>();
        break;
}
...