2011-09-08 34 views
12

Tôi đã sau sau khi làm một số nghiên cứu về các vấn đề khác:Sử dụng Unity Dependency Injection với các dịch vụ WCF

MyServiceHost:

public class MyServiceHost : ServiceHost 
{ 
    public MyServiceHost(IUnityContainer 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 DependencyInjectionInstanceProvider(container)); 
     } 
    } 
} 

DependencyInjectionInstanceProvider:

public class DependencyInjectionInstanceProvider : IInstanceProvider, IContractBehavior 
{  
    private readonly IUnityContainer container;  
    public DependencyInjectionInstanceProvider(IUnityContainer 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.Teardown(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 

} 

MyServiceHostFactory :

public class MyServiceHostFactory : ServiceHostFactory 
{ 
    private readonly IUnityContainer container;  
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     return new MyServiceHost(this.container, serviceType, baseAddresses); 
    } 
} 

Dịch vụ email với một Constructor tiêm cố gắng:

public class EmailValidator : IEmailValidator 
{ 
    private IFakeDAL fakeDAL; 

    public EmailValidator(IFakeDAL fakeDAL) 
    { 
     this.fakeDAL = fakeDAL; 
    } 

    public bool ValidateAddress(string emailAddress) 
    { 
     Console.WriteLine("Validating: {0}", emailAddress); 

     string pattern = @"^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@(([0-9a-zA-Z])+([-\w]*[0-9a-zA-Z])*\.)+[a-zA-Z]{2,9})$"; 
     return Regex.IsMatch(emailAddress, pattern); 
    } 
} 

My điều khiển máy chủ để bắt đầu Dịch vụ:

static void Main(string[] args) 
    { 
     Type serviceType = typeof(EmailValidator); 
     Uri serviceUri = new Uri("http://localhost:8080/"); 

     MyServiceHostFactory shf = new MyServiceHostFactory(); 
     ServiceHost host = shf.CreateServiceHost(serviceType, serviceUri); 
     //ServiceHost host = new ServiceHost(serviceType, serviceUri); 
     host.Open(); 

Vấn đề của tôi nằm trong logic giao diện điều khiển máy chủ . Cuộc gọi CreateServiceHost có lỗi cú pháp do đối số đầu tiên mong đợi một chuỗi Constructor và không phải là một Loại. Mà tôi không hiểu vì nó chấp nhận một tham số Type. Thêm vào đó, tôi không hiểu nơi tôi nên lập bản đồ IFakeDAL cho một lớp cụ thể. Tôi có thể làm điều đó trong một tập tin app.config hay tôi nên đăng ký ở một nơi khác?

Trả lời

7

ServiceHostFactory là để lưu trữ trong IIS. Trong tự lưu trữ, bạn nên sử dụng trực tiếp ServiceHost có nguồn gốc của bạn. Here bạn có toàn bộ ví dụ bao gồm cấu hình Unity.

+0

Cảm ơn. Nó trông giống như một ví dụ rất tốt. Tôi thực sự có thể tìm ra điều này. :) – Elim99

1

Các CreateServiceHost method hy vọng một mảng của Uri trường hợp, vì vậy hãy thử này để thay thế:

ServiceHost host = shf.CreateServiceHost(serviceType, new[] { serviceUri }); 

Bạn có thể lập bản đồ giao diện với các loại trong hoặc XML hoặc mã, nhưng tôi khuyên bạn nên mã, kể từ XML có quá cao phí bảo trì.

Phương pháp Main là một tuyệt vời Composition Root, nhưng nếu bạn muốn cấu hình container ở mức đó, bạn sẽ cần phải vượt qua nó từ phương pháp Main-MyServiceHostFactory - đó là hoàn toàn tốt đẹp khi bạn lưu trữ các dịch vụ trong một giao diện điều khiển ứng dụng, nhưng sẽ không hoạt động nếu bạn muốn lưu trữ nó trong IIS, trong đó MyServiceHostFactoryshould be the Composition Root, since IIS requires a default constructor.

+0

+1 để nhận xét về vị trí gốc của bố cục. BTW, yêu sách Mark. –

3

Tôi đang sử dụng các lớp sau trong dịch vụ cửa sổ của mình để tạo các dịch vụ WCF và tiêm phụ thuộc vào nó bằng cách sử dụng tính thống nhất.

UnityInstanceProvider:

internal class UnityInstanceProvider : IInstanceProvider { 

    private readonly IUnityContainer container; 
    private readonly Type contractType; 

    public UnityInstanceProvider(IUnityContainer container, Type contractType) { 
     this.container = container; 
     this.contractType = contractType; 
    } 

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

    public object GetInstance(InstanceContext instanceContext, Message message) { 
     return container.Resolve(contractType); 
    } 

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

UnityServiceBehavior:

public class UnityServiceBehavior : IServiceBehavior { 

    private readonly IUnityContainer container; 

    public UnityServiceBehavior(IUnityContainer container) { 
     this.container = container; 
    } 

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

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { 
    } 

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { 
     foreach (ChannelDispatcher channelDispatcher in serviceHostBase.ChannelDispatchers) { 
      foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) { 
       if (endpointDispatcher.ContractName != "IMetadataExchange") { 
        string contractName = endpointDispatcher.ContractName; 
        ServiceEndpoint serviceEndpoint = serviceDescription.Endpoints.FirstOrDefault(e => e.Contract.Name == contractName); 
        endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(this.container, serviceEndpoint.Contract.ContractType); 
       } 
      } 
     } 
    } 
} 

UnityServiceHost:

public class UnityServiceHost : ServiceHost { 

    private IUnityContainer unityContainer; 

    public UnityServiceHost(IUnityContainer unityContainer, Type serviceType) 
     : base(serviceType) { 
     this.unityContainer = unityContainer; 
    } 

    protected override void OnOpening() { 
     base.OnOpening(); 

     if (this.Description.Behaviors.Find<UnityServiceBehavior>() == null) { 
      this.Description.Behaviors.Add(new UnityServiceBehavior(this.unityContainer)); 
     } 
    } 
} 

Với các lớp này, bạn có thể thực hiện các thao tác sau (Cấu hình dịch vụ được thực hiện bằng .config):

UnityContainer container = new UnityContainer(); 
UnityServiceHost serviceHost = new UnityServiceHost(container, typeof("Type of Service to host")); 
serviceHost.Open(); 
+0

Vì vậy, bạn đang ánh xạ tới các lớp cụ thể trong tệp cấu hình của bạn? – Elim99

+0

Bạn có phiền khi hiển thị cấu hình dịch vụ trong tệp cấu hình không? – Elim99

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