2012-12-26 4 views
4

유형 매개 변수로 반사 형을 사용할 수 있습니까? 예 : 나는 전달 된 객체를 기반으로 persister 선택하려면 : 만 반사를 통해리플렉션의 유형을 유형 매개 변수로 사용할 수 있습니까?

IPersister GetPersisterFor(IEntity entity) 
{ 
    return GetPersisterFor<entity.GetType()>(); // <-- this cannot be compiled 
} 

IPersister GetPersisterFor<TEntity>() where TEntity : IEntity 
{ 
    //some logic to get persister... 
} 

답변

4

을; 일반 방법으로 을 얻으려면 GetMethod을 사용해야하고 그에 대해서는 MakeGenericMethod(entity.GetType()).Invoke(this, null);을 호출해야합니다. 행 (

return Evil((dynamic)entity); 

이 사용할 정확한 T를 검출하는 동적 표현식이 다음이다 : 단지 첫 번째 방법을

IPersister Evil<T>(T obj) where T : IEntity { 
    return GetPersisterFor<T>(); 
} 

및 메이크업 그러나

는 쉽게 동적 통하여 속이 인 악의에 찬 호출).

참고 : 추가 방법이 필요한 유일한 이유는 이름이 동일하기 때문에 재귀 적으로 다시 확인되지 않도록하는 것입니다.

+0

악이라고 부르는 이유는 무엇입니까? :) –

+0

@Rhys 왜냐하면 나는 그것을 무언가라고 부를 필요가 있었기 때문이다. –

+0

+1 또한, 호출 트리 위로 제네릭 형식 매개 변수'T'를 밀면된다. 어떤 시점에서,'entity'의 정확한 타입은 아마 알려질 것입니다. 그래서 그 시점부터'GetPersisterFor'까지의 모든 메소드가'T'를 generic 타입으로 유지한다면'dynamic'을 사용할 필요가 없습니다. 이것이 가능하지 않다면 (최상위 호출자는'IYo' 타입의 변수 만 사용할 수 있습니다), 이것은'MakeGenericMethod' 솔루션의 가장 좋은 지름길입니다. – jam40jeff

1

예, 일반 메소드 정의를 가져와야합니다. 그런 다음 MethodInfo.MakeGenericMethod을 사용하여 일반 메소드를 구성 할 수 있습니다.

그래서 같은 것을 : 모두 일반 및 비 일반적인 방법은 같은 이름을 가지고 있기 때문에, 당신은 다음 적절한 하나를 찾기 위해 클래스의 모든 방법을 반복하고,해야

MethodInfo genericMethodDefinition = GetType() 
    .GetMethods(BindingFlags.Instance | BindingFlags.NonPublic) 
    .Where(method => method.IsGenericMethod && method.Name == "GetPersisterFor") 
    .First(); 

// OR 

MethodInfo genericMethodDefinition = GetType().GetMethod("GetPersisterFor", 
    BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null); 

// THEN 

MethodInfo genericMethod = genericMethodDefinition.MakeGenericMethod(entity.GetType()); 
genericMethod.Invoke(this, null); 
+0

GetMethod에서 a : 비공개 메소드에 액세스해야하고 b : 동일하지 않은 일반 메소드와 비 일반 메소드간에 좀 더 명확해야합니다. 이름 –

+0

@MarcGravell, 고마워. –

1

그것을 호출 :

public IPersister GetPersisterFor(IEntity entity) 
{  
    MethodInfo getPersisterForGenericMethod = 
        GetType().GetMethods() 
         // iterate over all methods to find proper generic implementation 
         .Single(methodInfo => methodInfo.Name == "GetPersisterFor" && methodInfo.IsGenericMethod) 
         // supply it with generic type parameter 
         .MakeGenericMethod(entity.GetType()); 

    // invoke it 
    return getPersisterForGenericMethod.Invoke(this, null) as IPersister; 
} 

public IPersister GetPersisterFor<TEntity>() where TEntity : IEntity 
{ 
    return null; 
} 

ps : 전체 소스 코드를 gist.github

관련 문제