2012-12-14 5 views
2

API 사전 번호를 기반으로 내부 라우팅을 용이하게하기 위해 사용하는 사전이 있습니다. 본질적으로 어떤 일이 일어나는지는 내가 사전을 찾아서 조작하고 그것을 RUN 메서드라고 부르려고 시도한다. 그러나 이것을하기 위해서는 객체를 인터페이스에 캐스트 할 수 있어야합니다.리플렉션을 사용하여 일반 인터페이스로 전송하려면 어떻게해야합니까?

public Dictionary<string, Type> Routing = new Dictionary<string, Type>(); 

    public VersionRouter() 
    { 
     Routing.Add("1.0", typeof(OperationV1<RequestObjectV1, ResponseObjectV1>)); 
     Routing.Add("2.0", typeof(OperationV1<RequestObjectV2, ResponseObjectV1>)); 
     Routing.Add("3.0", typeof(OperationV1<RequestObjectV2, ResponseObjectV2>)); 
    } 

가 나는과 같이 인스턴스화 할 올바른 유형 잡아 수 있습니다 : 여기가 무슨 뜻이야,이 사전 정상적인 상황에서 다음

var myOperation = Routing["2.0"]; 

와, 난 그냥 인스턴스화 것 이런 식으로 캐스팅 :

var myInstance = (MyInterface) Activator.CreateInstance(myOperation); 

그러나, 인터페이스는 제네릭는 요청 및 응답 유형이 무엇인지 알 필요가 있기 때문에 :

이 요청 및 응답 유형이 현재 어떤 단계인지 알려주는 방법을 모르겠습니다. 나는 그것이 반사와 함께 할 수 있다고 가정하고있다. myOperation.GetGenericArguments()와 같은 것을 통해 일반 매개 변수를 가져올 수 있지만이 단계에서 내 이점을 사용하는 방법을 모르겠습니다. 누구든지이 작업을 수행하는 방법을 알고 있습니까?

답변

4

그건 본질적으로 불가능합니다.
런타임까지 유형 매개 변수를 알지 못하기 때문에 컴파일 타임에이 유형을 표현할 수 없습니다.
따라서 캐스팅하거나 해당 유형의 변수를 가질 수 없습니다.

가능하면 인터페이스를 공변수로 만들어 기본 유형을 사용하도록 캐스트해야합니다.

또는 일반 또는 공용이 아닌 기본 인터페이스를 만들어 대신 사용할 수 있습니다. SLaks을 확장하기 위해

+0

예제를 제공 할 수 있습니까? 전에 그런 짓을 한 적이 있는지 잘 모르겠다. – Sinaesthetic

+0

여기에서 공변 (covariant) 인터페이스에 대한 모든 것을 배울 수 있습니다 : [http://msdn.microsoft.com/en-us/library/dd997386.aspx] 본질은 유형에 대해 'out' 키워드로 인터페이스를 정의하는 것입니다. 인터페이스가 오류없이 덜 파생 된 클래스를 받아 들일 수 있음을 의미합니다. 까다로운 부분이지만 인터페이스를 디자인하는 방법에 대해 신중하지 않으면 몇 가지 흥미로운 버그를 소개 할 수 있습니다. –

4

대답 :

는 시나리오를 처리하는 논리적 방법은 없습니다. 당신이하려고하는 것은 런타임에 여러 유형의 코드가 작동하는 것입니다. 이것은 2 개의 별도 코드 브랜치 (수행 할 수있는)를 작성하거나 다이나믹/리플렉션으로 폴백함으로써 만 수행 할 수 있습니다. 이 문제를 명확히하기 위해 :

class Apple { } 
class Pear { } 

void Handle(object what) 
{ 
    // either 
if (what is Apple) {} 
else if (what is Pear) {} 

// or 
dynamic x = what; 
x.LetsHopeThisMethodExists(); 

// or 
what.GetType().GetMethod('lorem').Invoke(what, null); 
} 

이제 우리는 사과와 배, 즉 과일 모두에 대한 기본 형식을 선언 SLaks 제안을 고수 할 수 있습니다. 그렇게하면 Handle은 Fruit을 허용하고 apple과 pear 모두에서 사용할 수있는 공통 기능에 대한 논리를 수행 할 수 있습니다.

제네릭을 사용하는 방법에 대해 궁금한 점이 있습니다. Generics는 기본적으로 .NET 4.0에서 차이를 지원하지 않지만 확실히 가능합니다. type 매개 변수에 out 키워드를 적용하여 인터페이스 (단 하나의 인터페이스 만)를 공 변 (covariant)으로 선언 할 수 있습니다. 이를 통해 다음과 같은 작업을 수행 할 수 있습니다.

interface IFruit { } 
interface IBasket<out TFruit> where TFruit : IFruit { } 

class Apple : IFruit { } 
class Pear : IFruit { } 

class FruitBasket<TFruit> : IBasket<TFruit> where TFruit : IFruit { } 
void Handle(IBasket<IFruit> what) { } 

Handle(new FruitBasket<Apple>()); 
Handle(new FruitBasket<Pear>()); 
+0

훌륭하게 간결하지만 유익한 답변입니다. – ean5533

관련 문제