2010-01-29 4 views
-1

단위 테스트 WCF 서비스를 돕기 위해 몇 가지 코드를 작성하려고합니다. 이러한 서비스는 프록시 인스턴스를 생성 한 facade 클래스를 통해 액세스 한 다음 프록시 메소드를 호출하고 결과를 반환합니다. 각 프록시 메소드에 대해. 나는 현재 생성 코드를 실제 서비스 나 가짜 코드를 생성하는 것으로 대체 할 수 있기를 바란다.일반 제약 조건과 상속

나는 그것을 작동시키지 못했습니다. 나는 그것을 아래로 삶은 다음

using System.ServiceModel; 

namespace ExpressionTrees 
{ 
    public interface IMyContract 
    { 
     void Method(); 
    } 

    public class MyClient : ClientBase<IMyContract>, IMyContract 
    { 
     public MyClient() 
     { 
     } 

     public MyClient(string endpointConfigurationName) 
      : base(endpointConfigurationName) 
     { 
     } 

     public void Method() 
     { 
      Channel.Method(); 
     } 
    } 

    public class Test 
    { 
     public TClient MakeClient<TClient>() 
      where TClient : ClientBase<IMyContract>, IMyContract, new() 
     { 
      return new MyClient("config"); 

      // Error: 
      // Cannot convert expression of type 'ExpressionTrees.ServiceClient' to return type 'TClient' 
     } 
    } 
} 

이유는 MyClient 클래스가 나는 TClient를 반환하는 것을 의미하는 방법에서 MyClient 인스턴스를 반환 할 수없는, ClientBase<IMyContract>에서 유래와 IMyContract 구현에도 불구하고 있다는 점이다? TClient은 같은 것을 의미한다고 생각했던 유형 제한을 지정합니다.

public void CallClient<TClient>() 
     where TClient : ClientBase<IMyContract>, IMyContract 
    { 
     TClient client = null; 
     bool success = false; 
     try 
     { 
      client = MakeClient<TClient>(); 
      client.Method(); 
      client.Close(); 
      success = true; 
     } 
     finally 
     { 
      if (!success && client != null) 
      { 
       client.Abort(); 
      } 
     } 
    } 

하지만 그 대신 항상 MakeClient<TClient>를 호출, 내가 단위 테스트는 모의 객체를 주입 가질 수 있기를 원 :


내 목표는 다음과 같이 코드를 호출하는 것이 었습니다. 위의 코드는 모두 ClientBase<IMyContract>, IMyContract에 의존하기 때문에이 제약 조건을 충족시키는 일반 클래스를 "합성"하려고 시도한 것으로 보입니다.

돌이켜 볼 때 이는 의미가 없습니다. 예를 들어 ClientBase<IMyContract>Channel 개체가 구성되어 Close 메서드를 위임 할 수있는 방식으로 인스턴스화 될 것으로 예상됩니다.

실제 코드와 위조 된 서비스에 대해 동일한 코드가 실행될 때 나는 펑 소리를 냈습니다. 이제 IMyService을 주입하고 주입 된 속성이 null인지 여부에 따라 IMyService.Method 또는 client.Method을 호출합니다.

+1

나는 왜이 질문이 downvotes를 끄는 지 상상할 수 없다. 나는 downvoters 중 하나가 그 질문을 향상시킬 수 있도록 말해줬으면 좋겠다. –

답변

8

기본적으로 코드는 아래로 비등. 그러나 MakeFruit<Banana>()은 사과가 아니라 바나나를 반품해야합니다.

제네릭 형식 제약 조건의 의미는 호출자가 제공 한 형식 인수가 제약 조건과 일치해야한다는 것입니다. 따라서 예에서 MakeFruit<Banana>()이라고 할 수는 있지만 MakeFruit<Tiger>()이 아닐 수 있습니다. 왜냐하면 Tiger가 T가 Fruit로 변환 가능해야한다는 제약 조건과 일치하지 않기 때문입니다. 나는 당신이 제약이 뭔가 다른 것을 의미한다고 생각합니다. 그게 뭔지 잘 모르겠습니다.

이렇게 생각하십시오. 형식 매개 변수에는 형식 매개 변수 유형이 있습니다. 형식 매개 변수 유형은 인수로 사용되는 표현식의 유형을 제한합니다. 그래서 당신은 말할 때 : 당신이 말하는

void M(Fruit x) 

"M에서 형식 매개 변수 x를 위해 전달 된 인수는 과일로 변환해야합니다."

일반 유형 매개 변수 제약 조건은 완전히 동일합니다. 유형 유형 인수가 일반 유형 매개 변수에 전달 될 수있는 제한 사항입니다. "T : 과일"이라고 말하면 공식 매개 변수 목록에 (과일 x)라고 말하면됩니다. T는 과일에가는 형식이어야합니다. x에 대한 주장이 과일에 대한 논의가되어야하는 것과 같습니다.

왜 처음부터 제네릭 방식을 사용하고 싶습니까? 나는이 방법으로 정확히 모델링하려고하는 것이 무엇인지, 왜 그것이 일반적인 것인지를 왜 이해하려고하는지 이해하지 못한다.

+0

에릭, 예를 한 발 더 깊이 들어서서 내가하려는 일이 무엇인지 분명히 할 것입니다. –

3

반환 유형이 아닌 통화의 MakeClient<TClient>() 부분에서 TClient를 제한하고 있습니다.

반환 유형은 일반 매개 변수의 유형과 일치하지만, 사진을 가지고이 :이 유형을 반환해야 이후에 convertable되지 MyClientMakeClient<MyOtherClient>를 호출하여 유효한 반환, 또한입니다

public class MyOtherClient : ClientBase<IMyContract>, IMyContract 
{ 
    public void Method() 
    { 
     Channel.Method(); 
    } 
} 

MyOtherClient입니다. 에 반환을 변경하는 것을

참고 :

return new MyClient() as TClient; 

아마 컴파일러 과거를 얻을 수 있지만, 런타임시 내 위의 시나리오에서 null이 될 것입니다.

0

이렇게하면 문제가 해결됩니다. 당신이 MakeFruit<Banana>()를 호출하는 경우에도,

public static T MakeFruit<T>() where T : Fruit 
    { 
     return new Apple(); 
    } 

이 항상 사과를 반환

static T Make<T>() where T : IConvertible 
{ 
    var s = ""; 
    return (T)(Object)s;   
} 
+0

불행히도 아닙니다. 매개 변수화 된 생성자가 필요합니다. 나는 그것을 보여주기 위해 나의 질문을 업데이트했다. –

관련 문제