2011-01-14 3 views
2

Ich habe folgt als eine Klasse definiertfür überladene Funktion fehlt Method mit unterschiedlichem Rückgabetyp

interface ITest 
{ 
    List<T> Find<T>(int i); 
} 

class Test: ITest 
{ 
    public T List<T> Find<T>(int i) { return default(T); } 
    List<T> ITest.Find<T>(int i) { return null; } 
} 

Als ich typeof (Test) .GetMethods() verwenden (sowohl mit als auch ohne entsprechenden Binding) bekomme ich nicht die MethodInfo für ITest.Find-Funktion. Was ist der beste Weg, um die MethodInfo für die fehlende Methode zu erhalten?

Dank

+0

Diese nicht kompiliert. 'öffentliche T-Liste Suchen (int i) {Zurücksetzen Standard (T); } ' – Ani

+0

Da war ein Typo. der Code sollte öffentliche T-Liste lesen Finden (int i) ... – Charvak

Antwort

1

Ich glaube, Sie die folgende Signatur für die ersten Find Verfahren bedeuten:

public T Find<T>(int i) { return default(T); } 

(Ihre bestehende Deklaration nicht kompiliert, es hat zwei Return-Typ)

ich denke, das Problem ist, dass standardmäßig GetMethods nicht explizit implementierte Schnittstelle Methoden zurückgibt, die privat sind. Allerdings sollte es funktionieren mit diesen BindingFlags:

BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance 

Wenn Sie nur die beiden Find Methoden (und keiner der geerbten) wollen, werfen in einem BindingFlags.DeclaredOnly auch.

z.

static void Main(string[] args) 
{ 
    var flags = BindingFlags.NonPublic | BindingFlags.Public | 
       BindingFlags.Instance | BindingFlags.DeclaredOnly; 

    foreach(var method in typeof(Test).GetMethods(flags)) 
     Console.WriteLine(method); 
} 

Ausgang:

T Find[T](Int32) 
System.Collections.Generic.List`1[T] Program.ITest.Find[T](Int32) 
+0

Danke. Ich werde es versuchen. Warum ist ITest.Find privat? Wenn ich der Methode öffentlich hinzufüge, erhalte ich einen Compilerfehler. Und wie mache ich ITest.Find public? – Charvak

+1

Es ist privat, weil es eine * explizit * implementierte Schnittstellenmethode ist. Sie haben keine andere Wahl, als es auf diese Weise zu tun, solange die andere "Find" -Methode diese Signatur hat, weil sonst zwischen den beiden Methoden eine Mehrdeutigkeit besteht (überladene Methoden können nicht * nur * vom Rückgabetyp abweichen). Schließlich ist es nicht zulässig, Zugriffsmodifizierer an explizit implementierte Schnittstellenmethoden anzuhängen. – Ani

0

Sie Type.GetInterface nutzen könnten, stellen sicher, dass der Rückgabewert nicht null ist, und dann Reflexion über die es verwenden, um die Art zu bekommen. Zum Beispiel:

var @class = typeof(Test);  
var methods = @class.GetMethods();  
PrintMethods("Test", methods);  

methods = @class.GetInterface("ITest", true).GetMethods(); 
PrintMethods("ITest", methods); 

static void PrintMethods(string typeName, params MethodInfo[] methods) 
{ 
    Console.WriteLine("{0} methods:", typeName); 
    foreach(var method in methods) 
    { 
     Console.WriteLine("{0} returns {1}", method.Name, method.ReturnType); 
    } 
} 

Ausgänge (meinen Trennraumes Sperre):

Test methods: 
Find returns T 
ToString returns System.String 
Equals returns System.Boolean 
GetHashCode returns System.Int32 
GetType returns System.Type 

ITest methods: 
Find returns System.Collections.Generic.List`1[T] 

EDIT:

Obwohl Ani Antwort scheint dies ohne die Notwendigkeit für Sie zu lösen zurückgreifen, was hier vorgeschlagen wird.

0

können Sie Type.GetInterfaces verwenden, um alle Schnittstellen, die von einem Typ implementiert zu bekommen, so sollten folgend alle Methoden erhalten:

Type t = typeof(Test); 

IEnumerable<MethodInfo> methods = t.GetMethods() 
    .Concat(t.GetInterfaces().SelectMany(i => i.GetMethods())); 
+0

Ich werde das versuchen. Obwohl ohne Linq. Ich bin immer noch mit .net 2.0 fest. Wie auch immer, kann mir jemand sagen, was los ist? Die Funktion ist Teil der Klasse Test, also warum die methodInfo fehlt – Charvak

1

Ihre explizit implementiert ITest.Find Methode privat ist. Sie müssen Binding in Ihrem GetMethods verwenden nennen:

 var methods = typeof(Test).GetMethods(BindingFlags.Public | 
         BindingFlags.NonPublic | BindingFlags.Instance); 
+0

Der Code kompiliert nicht, wenn ich die ITest.Find-Funktion öffentlich hinzufüge. Wie mache ich ITest.Find öffentlich? – Charvak

+0

Explizit implementierte Interface-Methode soll nicht öffentlich sein. Überprüfen Sie Ihr Lieblingsbuch in C#. Aus diesem Grund empfehle ich Ihnen, BindingFlags.NonPublic zu verwenden. –

+0

Der Typ ist nicht generisch, daher ist 'typeof (Test <>)' nicht korrekt. Nur die Methoden sind generisch. – Ani