2015-02-05 3 views
0

으로 변환 할 수 없습니다. Func<ConstructorInfo, MyDelegate<T>>을 반환하는 메서드가 있습니다. 여기에서 MyDelegate은 일반 (공변인) 대리자입니다. 이제이 메소드의 결과를 Func<ConstructorInfo, MyDelegate<U>> 유형의 변수에 할당하고자합니다. 여기서 UT (T : U)의 기본 클래스입니다. 하지만 InvalidCastException이됩니다. 이것은 Func이 (적어도 .NET 3.5에서) 공변하지 않기 때문입니까, 아니면 어떻게 해결할 수 있습니까?Func <T1, T2<U>>을 Func <T1, T2<V>> V : U

편집 일부 코드 :

using System; 
using System.Reflection; 
using System.Linq.Expressions; 

public delegate T MyDelegate<out T>(params object[] args); 

class GenericTypeFactory 
{ 
    public static MyDelegate<T> GetActivator<T>(ConstructorInfo ctor) 
    { 
      // make a NewExpression that calls the ctor with the args we 
      // just created 
      var newExp = Expression.New(ctor); 
      var lambda = Expression.Lambda(typeof(MyDelegate<T>), newExp); 
      var compiledExpression = (MyDelegate<T>)lambda.Compile(); 
      return compiledExpression; 
    } 
} 

그리고 내 메인 클래스의

: 아직

using System; 
using System.Reflection; 
using System.Linq.Expressions; 

class MyClass { 
    private Func<ConstructorInfo, MyDelegate<T>> createLambdaExpression<T>() 
    { 
     // this Func is only introduced to ensure name-safety when 
     // refactoring the GenericTypeFactor.GetActivator-method 
     // (changing params, other name, ...) we could also use 
     // Reflection to get this method by its name the generic-type 
     // argument <T> is only a placeholder 
     Func<ConstructorInfo, Delegate> myFunc = 
      GenericTypeFactory.GetActivator<T>; 

     MethodInfo method = myFunc.Method; 
     // set the params for the method we obtained above 
     var paramExp = Expression.Parameter(typeof(ConstructorInfo), "ctor"); 
     // call the method with its params 
     var call = Expression.Call(method, paramExp);     
     return Expression.Lambda<Func<ConstructorInfo, MyDelegate<T>>>(
       call, 
       paramExp) 
      .Compile(); 
    } 

    void DoSomeThing<T>() 
    { 
     Type customType = typeof(T); // not really, but for simplicity 
     // type T is only a dummy-type (replaced in next line) 
     Func<Delegate> myFunc = this.createLambdaExpression<T>; 
     MethodInfo method = 
      myFunc.Method.GetGenericMethodDefinition() 
      .MakeGenericMethod(customType); 
     var getActivator = (Func<ConstructorInfo, MyDelegate<T>>) 
      method.Invoke(this, null); 
    } 
} 
+5

* .NET 3.5를 사용하고 있습니까? 환경에 대한 더 자세한 정보를 제공하면 도움이 될 것입니다. 문제를 보여주는 짧지 만 완전한 프로그램입니다. –

+0

Yeap, 3.5를 사용 중입니다. 그냥 잠깐 기다려주세요. 짧은 테스트 프로그램을 만들어야합니다 ... – HimBromBeere

+0

@JonSkeet .NET Framework 버전과 아무런 관련이 없습니다. –

답변

0

미안 그것은 내가 위의 게시 방법을 작동하지 않은 이유는 확실하지. 지금 나는 다른 방법을 발견했다, 그것이 적어도 작동한다 (비록 나의 아주 좋아하는 것이 아니다.). 이를 위해 필자는 createLambdaExpression-method의 결과를 구체적인 Func 대신 Delegate로 캐스팅하고 DynamicInvoke 메서드를 호출합니다. 이것은 물론 성능을 고려할 때 최적은 아니지만 모든 활성기를 캐시 할 때마다 특정 유형의 새 인스턴스가 필요합니다.

Func<Delegate> myFunc = this.createLambdaExpression<T>; 
MethodInfo method = myFunc.Method.GetGenericMethodDefinition().MakeGenericMethod(customType); 
var getActivator = (Delegate)method.Invoke(this, null); 
var activator = (Delegate)getActivator.DynamicInvoke(new[] { ctor }); 

마지막으로 나는 customType 유형의 새 인스턴스를 반환합니다.

관련 문제