具有Ninject WCF扩展的服务定位器免费架构

时间:2011-04-21 14:11:31

标签: .net ninject service-locator

我终于了解了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");

显式指定目标构造函数变量名称。不要看到任何伤害。但是,如果某人有更优雅和面向对象的方法 - 欢迎您回答。

1 个答案:

答案 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模块。