2016-09-22 1 views
0

나는 오버로드 된 메서드가 거의없는 클래스가 있습니다. 그 매개 변수의 유형별로 특정 것을 얻으려고합니다. 처음 두 개 (int 및 string 형식의 인수 사용)를 사용하면 비교적 쉽습니다. 그러나 내가 무엇을 하든지 내 프로그램이 제네릭 목록을위한 제 3의 프로그램에 주목할 수는 없습니다. 잘못된 Type 인수를 사용합니까? 그렇다면 올바른 방법은 무엇입니까?C# : 형식 (일반 목록)으로 GetMethod

/* rest of code */ 
    static void Main(string[] args) { 
     MethodInfo method = 
      typeof(c).GetMethod("m", new Type[] { typeof(int) }); 

     Console.WriteLine(method); 

     method = 
      typeof(c).GetMethod("m", new Type[] { typeof(String) }); 

     Console.WriteLine(method); 

     method = 
      typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<>) }); 

     Console.WriteLine(method); 

     Console.ReadKey(); 
    } 
} 

static class c 
{ 
    public static void m<T>(int i) 
    { 
    } 

    public static void m<T>(String s) 
    { 
    } 

    public static void m<T>(IEnumerable<T> Ls) 
    { 
    } 
} 
+0

[리플렉션을 사용하여 일반적인 방법을 호출하는 방법은 무엇입니까?] (http://stackoverflow.com/questions/232535/how-do-i-use-reflection-to -call-a-generic-method) – CSharpie

+0

@CSharpie 제네릭 메서드 자체를 얻는 방법에 대한 질문이 더 많습니다. 참조하는 질문에 대한 대답은 실제로 다루지 않습니다. – strongbutgood

답변

1

짧은 버전 : typeof(IEnumerable<>)typeof(IEnumerable<T>) (일부 T에 대한)과 동일하지 않습니다.

긴 버전 : 메소드 void c.m(IEnumerable<> Ls)은 일반 매개 변수가 특정 특정 위치에있을 때만 오버로드됩니다 - 런타임시 기존 - 일반 메소드의 인스턴스화를 참조하는 일부 코드로 인해 메소드를 작성하는 데 지터가 필요한 유형 .

테스트 코드에서 일반 메서드의 일부 인스턴스에 호출을 추가 한 다음 해당 인스턴스에 GetMethod을 수행하십시오. 일반 과부하에서 하나의 결과 만이

 
M 
    Int32 
M 
    IEnumerable`1 

참고 : 출력을 생성

using System.Collections.Generic; 
using System.Linq; 
using static System.Console; 

class Methods { 
    public static void M(int x)  { 
     // no-op 
    } 

    public static void M<T>(IEnumerable<T> x)  { 
     // no-op 
    } 
} 

class Program { 
    static void Main(string[] args) { 
     Methods.M(0); 
     Methods.M(new[] { "a", "b" }); 

     ShowAllM(); 
    } 

    public static void ShowAllM() { 
     var tm = typeof(Methods); 
     foreach (var mi in tm.GetMethods().Where(m => m.Name == "M")) 
     { 
      WriteLine(mi.Name); 
      foreach (var p in mi.GetParameters()) 
      { 
       WriteLine($"\t{p.ParameterType.Name}"); 
      } 
     } 
    } 
} 

:

는 다음과 같은 고려하십시오. M<char>(…)에 대한 호출이 Main에 추가 된 경우 출력은 과 같으며입니다. 반성

은이 인수가 "오픈 일반적인"성격을 반영, 단 하나 개의 방법이 있지만, 오픈 제네릭 형식으로 호출되는 등 상당히 동일하지 않습니다 (예를 들면. IEnumerable<>) 오픈 타입의 instantiatable 없습니다 .

은 세 번째 방법은 m<T>(IEnumerable<T>)의 서명이

+0

코드 예제를 추가 할 수 있습니까? 나는 그 인스턴스에 대해 _GetMethod가 무엇을 의미하는지 이해하지 못한다고 생각합니다. – Daedan

1

(나는. typeof(IEnumerable<>)typeof(IEnumerable<int>) 사이 디버거의 차이를보고 instruictive입니다. 여기에 기술적 인 세부 사항의 대부분은 과장 한)하지만 예는 보여줍니다 서명이 m(IEnumerable<>) 인 메소드를 찾으십시오.

typeof(IEnumerable<T>)typeof(IEnumerable<>)의 차이점은 전자는 제네릭 형식이고 두 번째 형식은 제네릭 형식 정의이며 이것들은 서로 다릅니다. 제네릭 형식은 제네릭 형식 정의와 제네릭 형식 인수에서 모두 결정됩니다. 사용하려는 것이 염두에두고

:

method = 
     typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<MyType>) }); 

당신이 방법으로 전달됩니다 열거의 유형을 대체합니다.

한편

당신이 제네릭 메서드 정의를 얻을 수 앞까지 열거의 유형을 알고 당신이 그것을 필요로 할 때 가능한 일반적인 방법을하지 않는 경우 : 당신이 일반적인 defenitions을 제거하면

methodDef = 
     typeof(c).GetMethod("m", new Type[] { typeof(IEnumerable<object>) }).GetGenericMethodDefinition(); 
method = methodDef.MakeGenericMethod(new Type[] { typeof(MyType) }); 
+0

그리고 방법에 대해 아무 것도 바꾸지 않고 얻을 수 있습니까? 현재 외부 라이브러리로 작업 중이므로 변경은 실제로 옵션이 아닙니다. GetMethods()에 의해 관련 MethodInfo를 가져 와서 올바른 방법으로 검색 할 수 있다는 것을 알고 있지만 _crude_ – Daedan

+0

@Daedan 예입니다. 메서드는 문제가 없으며 사용할 수있는 MethodInfo를 가져와야합니다. 그것이 당신이 원하는 것을 가정하면서 호출 할 수 있습니다. 일단 MethodInfo를 사용하면 어떻게 사용합니까? – strongbutgood

+0

'method = typeof (c) .GetMethod ("m", new Type [] {typeof (IEnumerable )});'는 null을 반환합니다. MethodInfo를 얻으려면 내 방법을 specyfically IEnumerable 인수로 수정해야합니다. – Daedan

0

을 INT 문자열 방법에서 :

public static void m(int i) 
    { 
    } 

    public static void m(String s) 
    { 
    } 

    public static void m<T>(IEnumerable<T> Ls) 
    { 
    } 

그리고 라인을 다음 사용을 필요로 얻을 수있는 일반적인 방법

method = typeof(c).GetMethods().FirstOrDefault(m => m.IsGenericMethod && 
        m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() 
         == typeof(IEnumerable<>)); 

트릭을 수행 할 것입니다

관련 문제