使用Ninject 2将参数传递给WCF ServiceHost类型

时间:2011-04-20 15:58:29

标签: c# wcf ninject

我想使用Ninject.Wcf扩展来创建参数化服务主机实例。

例如,我有一个类MyWCFHandler,只有以下构造函数:

public MyWCFHandler(UserManager manager)
{
  _manager = manager;
}

但是当我写var myServiceHost = new ServiceHost(typeof(MyWCFHandler));时,我无法将依赖项对象传递给构造函数。

我不想搞乱提供的自定义ServiceHost How do I pass values to the constructor on my wcf service?

我决定采用Ninject的方式,但不能完全理解如何在我的情况下采取行动。

以下是我理解Ninject中的WCF扩展工作原理:

  1. 在我的项目中引用Ninject和Ninject.Extensions.WCF。
  2. 创建一个继承Ninject模块的类,并编写如下内容:

    internal class ServiceModule : NinjectModule { public override void Load() { Bind<IUserManager>().To<UserManager>().WithConstructorParameters(myUserManagerIwantToUseInWCFHandler); } }

  3. 将使用新ServiceModule()初始化的内核添加到KernelContainer。

  4. 像这样使用NinjectServiceHost:

    var service = KernelContainer.Kernel.Get<IMyWCFHandler>(); _host = new NinjectServiceHost( service );

  5. 在那里我应该准备好我的主人才能打开。

    问题是:

    我应该如何将构造函数参数传递给NinjectModule?我准备好将参数绑定到它时,是否应该创建NinjectModule的实例?如何将它们传递给Get方法?

    不幸的是,没有一个示例可以简单地显示参数化的ServiceHost启动。我甚至不关心它是否是我使用的Ninject。无论哪种解决方案都有一个很好的例子 - 我很好,因为我只是决定使用什么IoC容器。

1 个答案:

答案 0 :(得分:6)

关于ninject。答案是,它取决于您是否需要单个服务或每个请求的新实例。使用单件服务,您可以执行以下操作:

public class TimeServiceModule : NinjectModule
{
    /// <summary>
    /// Loads the module into the kernel.
    /// </summary>
    public override void Load()
    {
        this.Bind<ITimeService>().To<TimeService>();

        this.Bind<ServiceHost>().ToMethod(ctx => ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("singletonInstance", c => c.Kernel.Get<ITimeService>())));
    }
}

internal static class Program
{
    private static void Main()
    {
        var kernel = new StandardKernel(new TimeServiceModule());

        var serviceHost = kernel.Get<ServiceHost>();
        serviceHost.AddServiceEndpoint(typeof(ITimeService), new NetTcpBinding(), "net.tcp://localhost/TimeService");
        try
        {
            serviceHost.Open();
        }
        finally
        {
            serviceHost.Close();
        }
    }
}

按要求方式:

public interface IServiceTypeProvider
{
    /// <summary>
    /// Gets the service types.
    /// </summary>
    /// <value>The service types.</value>
    IEnumerable<Type> Types { get; }
}

Func<Type, ServiceHost> serviceHostFactory

        foreach (Type serviceType in this.ServiceTypeProvider.Types)
        {
            // I do some magic here to query base contracts because all our service implement a marker interface. But you don't need this. But then you might need to extend the type provider interface.
            IEnumerable<Type> contracts = QueryBaseContracts(serviceType );

            var host = this.CreateHost(serviceType);

            foreach (Type contract in contracts)
            {
                Binding binding = this.CreateBinding();
                string address = this.CreateEndpointAddress(contract);

                this.AddServiceEndpoint(host, contract, binding, address);
            }

            host.Description.Behaviors.Add(new ServiceFacadeBehavior());

            this.OpenHost(host);

            this.serviceHosts.Add(host);
        }

    protected virtual ServiceHost CreateHost(Type serviceType )
    {
        return this.serviceHostFactory(serviceType );
    }

public class YourWcfModule : NinjectModule
{
    /// <summary>
    /// Loads the module into the kernel.
    /// </summary>
    public override void Load()
    {

        this.Bind<Func<Type, ServiceHost>>().ToMethod(
            ctx =>
            (serviceType) =>
            ctx.Kernel.Get<NinjectServiceHost>(new ConstructorArgument("serviceType", serviceType), new ConstructorArgument("baseAddresses", new Uri[] { })));
    }
}

玩得开心