【问题标题】:Passing parameters to a WCF ServiceHost type with Ninject 2使用 Ninject 2 将参数传递给 WCF ServiceHost 类型
【发布时间】:2011-08-09 15:30:25
【问题描述】:

我想使用 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. 将使用 new ServiceModule() 初始化的内核添加到 KernelContainer。

  4. 像这样使用 NinjectServiceHost:

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

我应该在那里准备好打开我的主机。

问题是:

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

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

【问题讨论】:

    标签: c# wcf ninject


    【解决方案1】:

    关于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[] { })));
        }
    }
    

    玩得开心

    【讨论】:

    • 谢谢。但是在这种情况下,为什么我需要一个 NinjectServiceHost 呢?我不能将 IUserManager 绑定到 Singleton Scope 中的 UserManager,然后从 TimeService 的构造函数中的全局可用内核中获取它吗?
    • 你可以。但这是著名的定位器模式方法。我总是建议尽可能多地进入组件不了解 DI 机制的方向。更清洁,更适合测试。
    • 事实证明,当我使用这种“singletonInstance”方法时,我绑定了InstanceContextMode.Single 服务行为,这不是我需要的。如何仍然绑定到具有构造函数参数的类,但将类型传递给 NinjectServiceHost 构造函数?
    • 海。编辑了上面显示每个请求解决方案的答案。如果需要,您可以询问更多详细信息
    猜你喜欢
    • 1970-01-01
    • 2012-12-21
    • 1970-01-01
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多