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