2011-04-20 62 views
3

我想使用Ninject.Wcf擴展來創建參數化服務主機實例。使用Ninject將參數傳遞給WCF ServiceHost類型2

比如我有一個類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方式提供,但不能完全瞭解如何在我的情況下采取行動。

這裏是我的理解WCF擴展在Ninject工作:

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

還有我應該有我的主人準備好打開。

的問題是:

我應該如何通過我的構造函數的參數爲​​NinjectModule?當我準備好將參數綁定到它時,我應該創建一個NinjectModule實例嗎?我如何將它們傳遞給Get方法?

不幸的是,沒有一個例子可以簡單地顯示參數化的ServiceHost啓動。我甚至不在乎它是否使用Ninject。無論哪種解決方案都有一個很好的例子 - 我對它很好,因爲我只是決定使用哪個IoC容器。

回答

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

玩得開心

+0

謝謝。但是爲什麼在這種情況下我需要一個NinjectServiceHost?難道我不能僅僅將IUserManager綁定到Singleton Scope中的UserManager,只是從我的TimeService的構造函數中的全局可用內核中獲取它? – 2011-04-20 23:25:51

+0

Hy你可以。但這是着名的定位模式方法。我總是建議您儘可能地去組件不瞭解DI機制的方向。更清潔,更好的測試。 – 2011-04-21 10:18:31

+0

事實證明,當我使用這種「singletonInstance」方法時,我將綁定到InstanceContextMode.Single服務行爲,這不是我所需要的。我怎樣才能仍然綁定到具有構造函數參數的類,但將類型傳遞給NinjectServiceHost構造函數? – 2011-04-21 14:33:35