我终于了解了Ninject如何处理DI,但是遇到了以下问题:
让我们假设我们有一个类,它将两个WCF ServiceHost对象作为构造函数参数:
public ActivitySinkServer(IDataProvider dataProvider, ServiceHost posClients, ServiceHost activitySinkOperatorClients)
起初我只有一个ServiceHost依赖项,所以我很容易处理这样的绑定:
public class CommunicationModule: NinjectModule
{
public override void Load()
{
Bind<POSClient>().ToSelf().WithConstructorArgument("posManager", Kernel.Get<POSManager>());
this.Bind<ServiceHost>().ToMethod(ctx => ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("singletonInstance", c => c.Kernel.Get<POSClient>())));
}
}
在这种情况下,我的ActivitySinkServer
可以通过使用单例对象初始化ServiceHost
来解决它的NinjectServiceHost
依赖关系。
现在,我有两个ServiceHost依赖项,我怎么能告诉Ninject哪一个提供哪个构造函数参数,仍然有我的内部代码Ninject-unaware。 (我知道我可以使用Ninject属性和手册中的其他内容)。
更新:
我继续使用
.When(request => request.Target.Name == "posClients");
.When(request => request.Target.Name == "activitySinkOperatorClients");
显式指定目标构造函数变量名称。不要看到任何伤害。但是,如果某人有更优雅和面向对象的方法 - 欢迎您回答。
答案 0 :(得分:0)
你这样做的方式是100%罚款;更“优雅”的方式是使用命名绑定或元数据。
顺便说一句,在这种情况下使用singletonInstance
的{{1}}构造函数要好得多 ,因为如果你以这种方式初始化它,那么WCF将不会允许你使用任何其他实例化模式(例如ServiceHost
)。让Ninject和WCF处理实例化,改为使用基于类型的构造函数。
命名绑定示例如下:
PerCall
请注意,初始化class ServiceModule : NinjectModule
{
public override void Load()
{
Bind<ServiceHost>().To<NinjectServiceHost>().Named("POS")
.WithConstructorArgument("serviceType", typeof(PosService))
.WithConstructorArgument("baseAddresses", new Uri[0]);
Bind<ServiceHost>().To<NinjectServiceHost>().Named("ActivitySink")
.WithConstructorArgument("serviceType", typeof(ActivitySink))
.WithConstructorArgument("baseAddresses", new Uri[0]);
}
}
public class Server
{
private readonly ServiceHost posHost;
private readonly ServiceHost activitySink;
public Server(IDataProvider dataProvider,
[Named("POS")] posHost,
[Named("ActivitySink")] activitySink)
{
this.posHost = posHost;
this.activitySink = activitySink;
}
}
构造函数参数对于Ninject选择正确的重载是必要的。将其初始化为baseAddresses
只会导致查找new Uri[0]
的默认行为以查找基址,因此不必担心传入空数组。
虽然这会将您的app.config
类与Ninject本身相关联,但通常您的Server
实例是在应用程序二进制文件而不是库中创建的,因此耦合不是问题。
我更喜欢ServiceHost
语法的这种方法,因为它在重构期间不太可能中断。有一天某人决定更改构造函数参数名称并不是不太可能,并且没有任何视觉指示任何依赖于这些名称的东西,也没有任何方法可以让Visual Studio自动重构来检测这种依赖。
所以,IMO,最好使用属性在这里明确依赖;这样,如果有人决定稍后添加第三个服务主机,他们会立即知道他们需要添加属性并更新相应的Ninject模块。