使用 Simple Injector 将两个特定的接口实现注入到构造函数中

Inject two specific interface implementations into constructor with Simple Injector

我有接口 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;
}

更新3 添加 workerType 分配示例。

workerType 是一个配置值。例如可以这样设置: workerType = Properties.Settings.Default.WorkerType;

我看到 2 个选项。

您可以使用 lambda 手动连接依赖项。这意味着您只需注册 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 注册和 link 注册到它们相应的构造函数参数。这允许 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;
}