2010-01-11 7 views
18

Miguel Castro처럼 제안 된 WCF 서비스가 있습니다. 즉, 모든 것을 수동으로 설정하고 ServiceHost 개체를 사용하여 내 서비스를 호스팅하는 콘솔 응용 프로그램을 보유하고 있음을 의미합니다.WCF 서비스에 데이터 주입

나는 얇은 내 서비스 클래스를 유지하려면, 그들은 현재 단지 행동 클래스에 대한 호출에 전달된다. 내 문제는 이제 단위 테스트 서비스 클래스입니다. 나는 이것을 모의하고 적절한 격리 된 단위 테스트를 작성할 수 있도록 생성자 매개 변수로 클래스에 무언가를 주입하려고합니다. ServiceHost 클래스는 인수를 허용하지 않는 것 같습니다. 그래서 제 질문은 어떻게 서비스 클래스에 데이터를 주입 할 수 있습니까?

+0

IoC 컨테이너를 사용하고 있습니까? 그렇다면 어느 것입니까? – Fabiano

+0

서버 쪽에서 아직 IoC 컨테이너를 사용하지 않습니다. 지금 소개 할 계획입니다. Prism과 함께 제공되는 클라이언트 측 Unity를 사용하고 있지만 서버에서 StructureMap 사용을 고려하십시오. 누구에게나 열려 있습니다. 귀하의 회신에 대해서는 – stiank81

답변

29

WCF 지원 생성자 삽입,하지만 당신은 거기에 도착하기 위해 약간의 농구를 뛰어 넘어야합니다. 핵심은 맞춤 ServiceHostFactory 작성에 있습니다. 그것도 기본 생성자가 있어야하지만, 모든 올바른 동작을 연결하는 데 사용할 수 있습니다.

는 예를 들어, 나는 최근에 서비스 구현에 대한 종속성을 묶는 성 윈저를 사용 하나를 썼다. CreateServiceHost의 구현은이 작업을 수행 :

this.container가 구성 IWindsorContainer입니다
return new WindsorServiceHost(this.container, serviceType, baseAddresses); 

.

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

및 WindsorInstanceProvider는 다음과 같습니다 :

WindsorServiceHost은 다음과 같습니다

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 
} 

이 많이처럼 보이지만 그것은 오히려이 재사용 가능한 범용 코드입니다 것을 알 수 있습니다 낮은 순환 복잡성.

다른 DI 컨테이너 또는 Poor Man 's DI를 사용하여 동일한 코딩 관용구를 따라 종속성 주입을 구현할 수 있습니다.

여기 가난한 사람의 DI를 사용하는이 관용구의 older writeup입니다.

+0

Thx입니다. 약속하는 것처럼 보인다! 내일 그것에 digg 할 것이다! – stiank81

+0

매우 유용한 답변입니다. –

+0

Wcf 기능을 사용하는 것보다이 접근법의 장점은 무엇입니까 ??? – CrazyDart

1

서비스를 싱글 톤으로 구성 했습니까? DI 컨테이너를 사용하여 서비스 인스턴스를 생성 할 때 IInstanceProvider 구현이 문제가 될 수 있다는 것을 알았습니다.

5

것은 당신이 성 윈저를 사용한다면, 그것은 더 쉽게이 작업을 수행 할 수있는 좋은 WCF 통합 시설, 많이있다.

관련 문제