1

我终于对 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 不知道。(我知道我可以使用手册中的 Ninject 属性和其他内容)。

更新:

我继续使用

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

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

4

1 回答 1

0

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

顺便说一句,在这种情况下最好不要使用 的singletonInstance构造函数ServiceHost,因为如果你这样初始化它,那么 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 模块。

于 2011-08-14T20:48:08.660 回答