2014-01-23 3 views
8

GetRuntimeMethod를 호출하면 다음과 같은 경우에 null이 반환되는 이유에 대한 단서가 있습니까? 나는 다음과 같은 코드를 실행하여 디버깅을 시도RuntimeReflectionExtensions.GetRuntimeMethod가 예상대로 작동하지 않습니다.

_castMethod = typeof(Enumerable).GetRuntimeMethod("Cast", new Type[] { typeof(IEnumerable) }); 

: 것은이가하는 것처럼 작동합니다

_toListMethod = typeof(Enumerable).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable<>) }); 

놀랍게도

var bah = typeof (Enumerable).GetRuntimeMethods().Where(m => m.Name.Contains("ToList")); 
var derp = bah.First().GetParameters(); 

는, 첫 번째 줄은 반환 내가 얻으려고하는 MethodInfo를 포함하는 콜렉션과 두 번째 라인은 예상되는 매개 변수 유형이 IEnumerable <>임을 확인합니다.

두 가지 메서드 서명인 Cast와 ToList는 비슷하며 ToList에 대한 MethodInfo를 가져 오는 것이 실패하는 이유가 없습니다.

이 코드는 TargetFrameworkProfile이 Profile78로 설정된 휴대용 클래스 라이브러리에서 실행됩니다.

감사합니다.

업데이트 : 나는 좋은 해결책이 될 때까지, 나를 위해 작동 한 추한 해결 방법은 : 나는 서명을 보였다

_toListMethod = typeof(Enumerable).GetRuntimeMethods().First(m => m.Name.Contains("ToList")); 

답변

3

, 그들은 다음과 같이 :

public static List<TSource> ToList<TSource>(this IEnumerable<TSource> source); 
public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source); 

나는 와 계속되는 뭔가가 생기고 일반 매개 변수가있는 확장 방법이 작동하지 않으므로 일 것이라고 생각합니다.

var intToListMethod = typeof(IEnumerable<int>).GetRuntimeMethod("ToList", new Type[] { typeof(IEnumerable<int>) }); 

시간이 오래 걸리며 필요한 동작을 위해 유효한 확장 메서드를 만들려고했습니다. 아래 코드 조각을 만들었습니다. 그것은 나를 위해 작동합니다. 이 불려

public static class RuntimeMethodExtensions 
{ 
public static MethodInfo GetRuntimeMethodsExt(this Type type, string name, params Type[] types) 
{ 
    // Find potential methods with the correct name and the right number of parameters 
    // and parameter names 
    var potentials = (from ele in type.GetMethods() 
        where ele.Name.Equals(name) 
        let param = ele.GetParameters() 
        where param.Length == types.Length 
        && param.Select(p => p.ParameterType.Name).SequenceEqual(types.Select(t => t.Name)) 
        select ele); 

    // Maybe check if we have more than 1? Or not? 
    return potentials.FirstOrDefault(); 
} 
} 

: 내 세 번째 경우와 이가지 경우를 컴파일 할 때

var myLookup = typeof(Enumerable).GetRuntimeMethodsExt("ToList", typeof(IEnumerable<>)); 

나는 IL 첨부했습니다 아래의 생산. ToList 메서드 중 아무 것도 결과를 생성하지 않습니다.

당신이 기대
// ToList<int> 
IL_0001: ldtoken  System.Collections.Generic.IEnumerable<System.Int32> 
IL_0006: call  System.Type.GetTypeFromHandle 
IL_000B: ldstr  "ToList" 
IL_0010: ldc.i4.1  
IL_0011: newarr  System.Type 
IL_0016: stloc.3  // CS$0$0000 
IL_0017: ldloc.3  // CS$0$0000 
IL_0018: ldc.i4.0  
IL_0019: ldtoken  System.Collections.Generic.IEnumerable<System.Int32> 
IL_001E: call  System.Type.GetTypeFromHandle 
IL_0023: stelem.ref 
IL_0024: ldloc.3  // CS$0$0000 
IL_0025: call  System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethod 
IL_002A: stloc.0  // _intToListMethod 
// ToList<> 
IL_002B: ldtoken  System.Linq.Enumerable 
IL_0030: call  System.Type.GetTypeFromHandle 
IL_0035: ldstr  "ToList" 
IL_003A: ldc.i4.1  
IL_003B: newarr  System.Type 
IL_0040: stloc.3  // CS$0$0000 
IL_0041: ldloc.3  // CS$0$0000 
IL_0042: ldc.i4.0  
IL_0043: ldtoken  System.Collections.Generic.IEnumerable<> 
IL_0048: call  System.Type.GetTypeFromHandle 
IL_004D: stelem.ref 
IL_004E: ldloc.3  // CS$0$0000 
IL_004F: call  System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethod 
IL_0054: stloc.1  // _toListMethod 
// Cast<> 
IL_0055: ldtoken  System.Linq.Enumerable 
IL_005A: call  System.Type.GetTypeFromHandle 
IL_005F: ldstr  "Cast" 
IL_0064: ldc.i4.1  
IL_0065: newarr  System.Type 
IL_006A: stloc.3  // CS$0$0000 
IL_006B: ldloc.3  // CS$0$0000 
IL_006C: ldc.i4.0  
IL_006D: ldtoken  System.Collections.Generic.IEnumerable<> 
IL_0072: call  System.Type.GetTypeFromHandle 
IL_0077: stelem.ref 
IL_0078: ldloc.3  // CS$0$0000 
IL_0079: call  System.Reflection.RuntimeReflectionExtensions.GetRuntimeMethod 
IL_007E: stloc.2  // _castMethod 
+0

좋은 지적. Cast 메서드에 제네릭이 아닌 매개 변수 형식이 있습니다. 나는 당신과 동의합니다, 일반적인 매개 변수 유형과 관련이있는 것처럼 보입니다. –

+1

@TiagoMargalho 나는 가능한 확장 메소드를 추가했다. (가능한 한 복사 - 붙여 넣기가 아무 것도 깨지 않았 음) 가능한 메소드를 거치고 타입 매개 변수의 이름으로 검사했다. 이 경우에는 훌륭하게 작동하지만 위험한 길을 걸을 수 있다고 생각합니다 :) – flindeberg

0

...

대해서 typeof (Enumerable에서) .GetRuntimeMethod ("ToList", 새로운 유형 [] {대해서 typeof (IEnumerable을 <>)});

...이를 반환하는 ...

공공 정적 목록 ToList (이 IEnumerable을 소스); 당신이 생각하기 때문에

은 ... 매개 변수 source의 유형은 typeof(IEnumerable<>) 같다. 그렇지 않습니다.source의 형식은 IEnumerable<TSource>이고 typeof(IEnumerable<>)의 형식은 ToList 메서드로 정의 된 제네릭 형식 매개 변수를 사용하는 후자 (일반 형식 정의)의 인스턴스입니다.

일반적으로 C#은 메서드에 정의 된 일반 매개 변수를 나타내는 형식을 가져 오는 간단한 방법 (비 반사)을 제공하지 않으므로 이러한 메서드에 바인딩하기위한 간단한 API를 정의하기가 어렵습니다.

관련 문제