【问题标题】:Service locator free architecture with Ninject WCF Extenstion带有 Ninject WCF 扩展的无服务定位器架构
【发布时间】:2011-08-10 08:35:41
【问题描述】:

我终于对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 可以通过使用单例对象初始化的NinjectServiceHost 来解决它的ServiceHost 依赖项。

现在,我有两个 ServiceHost 依赖项,我如何告诉 Ninject 在哪个构造函数参数处提供哪个,仍然让我的内部代码 Ninject 不知道。 (我知道我可以使用手册中的 Ninject 属性和其他内容)。

更新:

我继续使用,只是使用了

.When(request => request.Target.Name == "posClients");
.When(request => request.Target.Name == "activitySinkOperatorClients");

明确指定目标构造函数变量名。看不出有什么害处。但是,如果有人有更优雅和面向对象的方法 - 欢迎您回答。

【问题讨论】:

    标签: .net ninject service-locator


    【解决方案1】:

    你这样做的方式是 100% 好的;更“优雅”的做法是使用命名绑定或元数据。

    顺便说一句,在这种情况下,最好不要使用ServiceHost 的singletonInstance 构造函数,因为如果你这样初始化它,那么WCF 将不允许你使用任何其他的实例化模式(如PerCall)。让 Ninject 和 WCF 处理实例化并改用基于类型的构造函数。

    命名绑定示例如下:

    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;
        }
    }
    

    请注意,初始化 baseAddresses 构造函数参数对于 Ninject 选择正确的重载是必要的。将其初始化为 new Uri[0] 只会导致默认行为在 app.config 中查找基地址,因此不必担心传入空数组。

    尽管这会将您的 Server 类与 Ninject 本身耦合,但通常您的 ServiceHost 实例是在应用程序二进制文件而不是库中创建的,因此耦合不是问题。

    我更喜欢When 语法的这种方法,因为它在重构期间不太可能中断。总有一天有人会决定更改构造函数参数名称,并且没有任何视觉指示表明任何东西都依赖于这些名称,Visual Studio 的自动重构也没有任何方法可以检测到这种依赖关系。

    所以,IMO,最好在此处使用属性明确依赖关系;这样,如果有人决定稍后添加 第三个​​ 服务主机,他们会立即知道他们需要添加属性并更新相应的 Ninject 模块。

    【讨论】:

      猜你喜欢
      • 2013-04-15
      • 1970-01-01
      • 2011-03-28
      • 1970-01-01
      • 2011-06-20
      • 1970-01-01
      • 2011-07-24
      • 2011-12-26
      • 1970-01-01
      相关资源
      最近更新 更多