2010-08-12 86 views
11

我有,我想用我的資料庫和我想的依賴注入到我的WCF Web服務服務一個WCF Web服務,然而Ninject WCF擴展例子非常具有構造函數這是實例化每個依賴項的實例,我不想要,我想要一個純粹的依賴注入。使用Ninject WCF擴展與WCF Web服務

有沒有人有使用Ninject與WCF任何成功,谷歌似乎有點返回相關結果我要找的主題。

回答

8

背後的代碼TimeService有:

<%@ ServiceHost Language="C#" Debug="true" Service="WcfTimeService.TimeService" CodeBehind="TimeService.svc.cs" **Factory="Ninject.Extensions.Wcf.NinjectServiceHostFactory"** %> 

bastard injection構建函數混淆事 - Ninject會選擇最具體的構造。與樣品普遍的問題是,它涵蓋所有的基礎(IIS託管,EXE託管,服務託管)和WCF犯規究竟做出所有這些東西易於管理或者(@Ian戴維斯:我很容易被錯誤的,可以爲您提供一些更詳細的請,也許是在什麼樣的樣本說明自述,並在爲什麼你使用過BI的各類案件或許更詳細的摘要形式?)

2

我目前正在使用的方式Ninject(v3)與我的WCF基於Ninject WCF擴展和Pieter De Rycke's great blog post

概括地說,這裏是我在做什麼:

1)通過的NuGet,我已經加入到Ninject.Extensions.Wcf參考到我的WCF項目。這將創建帶有NinjectWebCommon.cs的App_Start文件夾,該文件夾負責初始化Ninject。

2)通常情況下,你會設置你的Ninject映射在NinjectWebCommon.cs的CreateKernel方法。然而,由於我有相同的解決方案一個MVC3的網站,並希望該站點的相同Ninject映射,我CreateKernel看起來是這樣的:

private static IKernel CreateKernel() 
    { 
     var kernel = new StandardKernel(); 
     kernel.Bind<Func<IKernel>>().ToMethod(ctx =>() => new Bootstrapper().Kernel); 
     kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>(); 

     InfrastructureSetup.RegisterServices(kernel); 
     return kernel; 
    } 

3)在InfrastructureSetup.RegisterServices,我有我的Ninject映射:

public static class InfrastructureSetup 
{ 
    public static void RegisterServices(IKernel kernel) 
    { 
     kernel.Bind<IRepositoryContext>().To<MyEntityFrameworkContext>().InRequestScope(); 
     kernel.Bind<IFooRepository>().To<FooRepository>().InRequestScope(); 
     kernel.Bind<IBarRepository>().To<BarRepository>().InRequestScope(); 

     // ... and so on. I want InRequestScope() for the EF context, since 
     // otherwise my repositories (which take IRepositoryContext in their 
     // constructors) end up getting different EF contexts, messing things up 
    } 
} 

4)我也想注入的東西(IFooService等)到我的WCF的構造函數,所以我修改了WCF項目的Web.config與彼得·德·Rycke建議:

<behaviors> 
     <serviceBehaviors> 
      <behavior name=""> 
       <serviceMetadata httpGetEnabled="true" /> 
       <serviceDebug includeExceptionDetailInFaults="false" /> 
       <!-- Add the Ninject behavior to the WCF service. This is needed to support dependency injection to the WCF constructors --> 
       <ninject /> 
      </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    <extensions> 
    <behaviorExtensions> 
     <!-- Add the Ninject behavior extension --> 
     <add name="ninject" 
     type="MyWCFProject.Infrastructure.NinjectBehaviorExtensionElement, MyWCFProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 
    </behaviorExtensions> 
    </extensions> 

5)在MyWCFProject.Infrastructure命名空間,我有三個文件,這是從彼得基本上是複製粘貼:

NinjectBehaviorAttribute.cs:

using System; 
using System.Collections.ObjectModel; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Description; 
using System.ServiceModel.Dispatcher; 
using Ninject.Web.Common; 

namespace MyWCFProject.Infrastructure 
{ 
public class NinjectBehaviorAttribute : Attribute, IServiceBehavior 
{ 
    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, 
     Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
     Type serviceType = serviceDescription.ServiceType; 

     // Set up Ninject to support injecting to WCF constructors 
     var kernel = new Bootstrapper().Kernel; 
     IInstanceProvider instanceProvider = new NinjectInstanceProvider(kernel, serviceType); 

     foreach (ChannelDispatcher dispatcher in serviceHostBase.ChannelDispatchers) 
     { 
      foreach (EndpointDispatcher endpointDispatcher in dispatcher.Endpoints) 
      { 
       DispatchRuntime dispatchRuntime = endpointDispatcher.DispatchRuntime; 
       dispatchRuntime.InstanceProvider = instanceProvider; 
      } 
     } 
    } 

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) 
    { 
    } 
} 
} 

NinjectBehaviorExtensionElement.cs:

using System; 
using System.ServiceModel.Configuration; 

namespace MyWCFProject.Infrastructure 
{ 
    public class NinjectBehaviorExtensionElement : BehaviorExtensionElement 
    { 
     public override Type BehaviorType 
     { 
      get { return typeof(NinjectBehaviorAttribute); } 
     } 

     protected override object CreateBehavior() 
     { 
      return new NinjectBehaviorAttribute(); 
     } 
    } 
} 

NinjectInstanceProvider .cs:

using System; 
using System.ServiceModel; 
using System.ServiceModel.Channels; 
using System.ServiceModel.Dispatcher; 
using Ninject; 

namespace MyWCFProject.Infrastructure 
{ 
    public class NinjectInstanceProvider : IInstanceProvider 
    { 
     private Type serviceType; 
     private IKernel kernel; 

     public NinjectInstanceProvider(IKernel kernel, Type serviceType) 
     { 
      this.kernel = kernel; 
      this.serviceType = serviceType; 
     } 

     public object GetInstance(InstanceContext instanceContext) 
     { 
      return this.GetInstance(instanceContext, null); 
     } 

     public object GetInstance(InstanceContext instanceContext, Message message) 
     { 
      return kernel.Get(this.serviceType); 
     } 

     public void ReleaseInstance(InstanceContext instanceContext, object instance) 
     { 
     } 
    } 
} 

在mo這個解決方案似乎運作良好;依賴注入正在爲WCF和MVC3站點工作,我可以請求依賴注入到WCF構造函數中,並且EF上下文在請求期間保持不變。