2010-01-11 36 views
18

Tôi có các dịch vụ WCF được cấu trúc như được đề xuất bởi Miguel Castro. Điều này có nghĩa là tôi đã thiết lập mọi thứ theo cách thủ công và có ứng dụng bảng điều khiển lưu trữ dịch vụ của tôi bằng cách sử dụng các đối tượng ServiceHost.Tiêm dữ liệu vào dịch vụ WCF

Tôi muốn giữ các lớp dịch vụ của mình mỏng và hiện tại họ chỉ chuyển các cuộc gọi đến các lớp hành vi. Vấn đề của tôi bây giờ là kiểm tra đơn vị các lớp dịch vụ. Tôi muốn tiêm một cái gì đó để các lớp học như là một tham số constructor như vậy mà tôi có thể giả mạo này đi và viết các bài kiểm tra đơn vị cô lập thích hợp. Lớp ServiceHost dường như không chấp nhận các đối số, vì vậy câu hỏi của tôi là làm thế nào tôi có thể tiêm dữ liệu vào các lớp dịch vụ - hay tôi không thể?

+0

bạn có đang sử dụng thùng chứa IoC không? và nếu có cái nào? – Fabiano

+0

Tôi chưa sử dụng IoC-container ở phía máy chủ. Lên kế hoạch giới thiệu một cái bây giờ. Đang sử dụng Unity ở phía máy khách (vì nó đi kèm với Prism), nhưng hãy xem xét sử dụng StructureMap trên máy chủ. Mở cho bất kỳ ai thực sự. – stiank81

Trả lời

29

WCF hỗ trợ Constructor Injection, nhưng bạn phải nhảy qua một vài vòng để đến đó. Chìa khóa nằm trong văn bản một ServiceHostFactory tùy chỉnh. Trong khi đó, quá, phải có một constructor mặc định, bạn có thể sử dụng nó để dây lên tất cả các hành vi chính xác.

Ví dụ, gần đây tôi đã viết một trong đó sử dụng Castle Windsor để dây phụ thuộc cho việc thực hiện dịch vụ. Việc triển khai CreateServiceHost chỉ cần thực hiện điều này:

return new WindsorServiceHost(this.container, serviceType, baseAddresses); 

nơi this.container là IWindsorContainer được định cấu hình.

WindsorServiceHost trông như thế này:

public class WindsorServiceHost : ServiceHost 
{ 
    public WindsorServiceHost(IWindsorContainer container, Type serviceType, params Uri[] baseAddresses) 
     : base(serviceType, baseAddresses) 
    { 
     if (container == null) 
     { 
      throw new ArgumentNullException("container"); 
     } 

     foreach (var cd in this.ImplementedContracts.Values) 
     { 
      cd.Behaviors.Add(new WindsorInstanceProvider(container)); 
     } 
    } 
} 

và WindsorInstanceProvider trông như thế này:

public class WindsorInstanceProvider : IInstanceProvider, IContractBehavior 
{ 
    private readonly IWindsorContainer container; 

    public WindsorInstanceProvider(IWindsorContainer container) 
    { 
     if (container == null) 
     { 
      throw new ArgumentNullException("container"); 
     } 

     this.container = container; 
    } 

    #region IInstanceProvider Members 

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

    public object GetInstance(InstanceContext instanceContext) 
    { 
     var serviceType = instanceContext.Host.Description.ServiceType; 
     return this.container.Resolve(serviceType); 
    } 

    public void ReleaseInstance(InstanceContext instanceContext, object instance) 
    { 
     this.container.Release(instance); 
    } 

    #endregion 

    #region IContractBehavior Members 

    public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 
    { 
    } 

    public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime) 
    { 
    } 

    public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime) 
    { 
     dispatchRuntime.InstanceProvider = this; 
    } 

    public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint) 
    { 
    } 

    #endregion 
} 

này có thể trông giống như rất nhiều, nhưng nhận thấy rằng đó là tái sử dụng, mã mục đích chung mà có một thay độ phức tạp chu kỳ thấp.

Bạn có thể thực hiện theo cùng một thành ngữ mã hóa để triển khai Dependency Injection với một DI Container khác hoặc bằng cách sử dụng DI của người nghèo.

Đây là một số older writeup của thành ngữ này sử dụng DI của người nghèo.

+0

Thx cho câu trả lời của bạn. Trông promissing! Sẽ digg vào nó vào ngày mai! – stiank81

+0

Câu trả lời rất hữu ích. –

+0

Lợi thế của phương pháp này thay vì sử dụng cơ sở Wcf là gì? – CrazyDart

1

bạn có định cấu hình dịch vụ của mình thành Singleton không? tôi phát hiện ra rằng việc triển khai IInstanceProvider có thể có vấn đề khi sử dụng vùng chứa DI để tạo các cá thể dịch vụ.

5

Nếu bạn đang sử dụng Castle Windsor, nó có một cơ sở WCF tích hợp tuyệt vời cho phép bạn làm điều này, và rất nhiều rất dễ dàng.

0

Bài viết Hosting a Mock as a WCF service chứa phương pháp tĩnh sẽ tạo máy chủ lưu trữ dịch vụ WCF dựa trên đối tượng được chuyển vào phương thức với một điểm cuối duy nhất.

Phương thức cũng được đăng trong answer cho Recommended patterns for unit testing web services.

Ví dụ về các cuộc gọi sử dụng NSubstitute, nhưng có thể sử dụng các công cụ tạo hình nhại khác.

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