2010-08-12 24 views
11

Tôi có dịch vụ web WCF mà tôi muốn sử dụng Kho lưu trữ và Dịch vụ mà tôi muốn phụ thuộc vào dịch vụ web WCF của mình, tuy nhiên ví dụ Phần mở rộng WCF Ninject khá nhiều đó là khởi tạo một cá thể của mỗi phụ thuộc, mà tôi không muốn, tôi muốn tiêm một sự phụ thuộc tinh khiết hơn.Sử dụng Tiện ích mở rộng WCF Ninject với Dịch vụ Web WCF

Có ai có bất kỳ thành công nào với việc sử dụng Ninject với WCF, Google dường như trả lại ít kết quả có liên quan cho các chủ đề tôi đang tìm kiếm.

Trả lời

8

Các mã sau cho TimeService có:

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

Các bastard injection ctors nhầm lẫn vấn đề này - Ninject sẽ chọn các nhà xây dựng cụ thể nhất. Vấn đề chung với mẫu là nó bao gồm tất cả các cơ sở (IIS Hosted, EXE được lưu trữ, dịch vụ lưu trữ), và WCF không chính xác làm cho tất cả các công cụ này dễ quản lý hoặc (@Ian Davis: Tôi có thể dễ dàng sai, bạn có thể cung cấp một số chi tiết xin vui lòng, có lẽ trong các hình thức của một bản tóm tắt những gì các mẫu minh họa trong README, và có lẽ chi tiết hơn trong lý do tại sao các trường hợp khác nhau mà bạn đã sử dụng BI?)

2

Cách tôi hiện đang sử dụng Ninject (v3) với WCF của tôi dựa trên phần mở rộng WCF Ninject và Pieter De Rycke's great blog post.

Tóm lại, đây là những gì tôi đang làm:

1) Via NuGet, tôi đã thêm một tham chiếu đến Ninject.Extensions.Wcf vào dự án WCF của tôi. Điều này tạo ra thư mục App_Start với NinjectWebCommon.cs, nó sẽ xử lý việc khởi tạo Ninject.

2) Thông thường, bạn sẽ thiết lập ánh xạ Ninject của bạn trong phương thức CreateKernel trong NinjectWebCommon.cs. Tuy nhiên, kể từ khi tôi có một trang web MVC3 trong cùng một giải pháp và muốn ánh xạ Ninject cùng cho trang web đó, CreateKernel của tôi trông như thế này:

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) Trong InfrastructureSetup.RegisterServices, tôi có ánh xạ Ninject tôi:

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) tôi muốn cũng phải tiêm thứ (IFooService vv) để nhà xây dựng WCF của tôi, vì vậy tôi đã chỉnh sửa Web.config cho dự án WCF với những lời khuyên từ Pieter De 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) Trong không gian tên MyWCFProject.Infrastructure, tôi có ba file đó về cơ bản copy-paste từ Pieter:

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) 
     { 
     } 
    } 
} 

Tại mo ment, giải pháp này dường như hoạt động tốt; phụ thuộc tiêm đang làm việc cho cả WCF và trang MVC3, tôi có thể yêu cầu phụ thuộc được tiêm vào các nhà xây dựng WCF và bối cảnh EF ở lại trong suốt thời gian yêu cầu.

Các vấn đề liên quan