2008-11-28 6 views
107

Edytuj:Wywołanie metody ogólnej z argumentem typu znanym tylko w czasie wykonywania

Oczywiście mój prawdziwy kod nie wygląda dokładnie tak. Próbowałem napisać pół-pseudo-kod, aby uczynić go bardziej jasnym od tego, co chciałem zrobić.

Wygląda na to, że po prostu coś pomieszało.

Więc co tak naprawdę chciałby zrobić to w ten sposób:

Method<Interface1>(); 
Method<Interface2>(); 
Method<Interface3>(); 
... 

Cóż ... Pomyślałem, że może mógłbym zamienić go w pętli przy użyciu odbicia. Pytanie brzmi: jak mam to zrobić. Mam bardzo słabą wiedzę o odbiciu. Przykłady kodu byłyby świetne.

Scenariusz wygląda następująco:

public void Method<T>() where T : class 
{} 
public void AnotherMethod() 
{ 
    Assembly assembly = Assembly.GetExecutingAssembly(); 

    var interfaces = from i in assembly.GetTypes() 
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here 
    select i; 

    foreach(var i in interfaces) 
    { 
     Method<i>(); // Get compile error here! 
    } 




Original post:

Cześć!

Próbuję pętli wszystkich interfejsów w obszarze nazw i wysłać je jako argumenty do ogólnego sposobu jak ten:

public void Method<T>() where T : class 
{} 
public void AnotherMethod() 
{ 
    Assembly assembly = Assembly.GetExecutingAssembly(); 

    var interfaces = from i in assembly.GetTypes() 
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here 
    select i; 

    foreach(var interface in interfaces) 
    { 
     Method<interface>(); // Get compile error here! 
    } 
} 

Błąd pojawia jest „Nazwa typu oczekiwaniami, ale nazwa lokalna zmienna znaleziono ". Gdy próbuję

... 
    foreach(var interface in interfaces) 
    { 
     Method<interface.MakeGenericType()>(); // Still get compile error here! 
    } 
} 

otrzymuję „nie można zastosować operatora«<»do argumentów typu«grupa metoda»i«System.Type»” Każdy pomysł, jak obejść ten problem?

Odpowiedz

133

EDYCJA: Okay, czas na krótki, ale kompletny program. Odpowiedź jest podstawowym jak poprzednio:

  • Znajdź "otwarte" metody rodzajowe z Type.GetMethod
  • uczynić rodzajowy użyciu MakeGenericMethod
  • Wywołuje ją Invoke

Oto niektóre przykładowy kod. Zauważ, że zmieniłem wyrażenie zapytania na notację kropkową - nie ma sensu używać wyrażenia zapytania, gdy w zasadzie masz tylko klauzulę where.

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

namespace Interfaces 
{ 
    interface IFoo {} 
    interface IBar {} 
    interface IBaz {} 
} 

public class Test 
{ 
    public static void CallMe<T>() 
    { 
     Console.WriteLine("typeof(T): {0}", typeof(T)); 
    } 

    static void Main() 
    { 
     MethodInfo method = typeof(Test).GetMethod("CallMe"); 

     var types = typeof(Test).Assembly.GetTypes() 
           .Where(t => t.Namespace == "Interfaces"); 

     foreach (Type type in types) 
     { 
      MethodInfo genericMethod = method.MakeGenericMethod(type); 
      genericMethod.Invoke(null, null); // No target, no arguments 
     } 
    } 
} 

odpowiedź Original

Zostawmy na bok oczywiste problemy z wywołaniem zmienną „interfejs” na początek.

Musisz zadzwonić po odbiciu. Celem generycznych jest wprowadzenie więcej sprawdzania typów w czasie kompilacji. Nie wiesz, jaki typ jest w trakcie kompilacji - dlatego musisz używać generycznych.

Uzyskaj ogólną metodę i wywołaj metodę MakeGenericMethod, a następnie wywołaj ją.

Czy twój typ interfejsu jest rzeczywiście ogólny? Pytam, ponieważ dzwonisz MakeGenericType na nim, ale nie przekazując żadnych argumentów typu ... Czy próbujesz zadzwonić

Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string) 

lub

Method<MyNamespace.Interface>(); 

Jeśli to ostatnie, to tylko potrzebują wywołanie MakeGenericMethod - nie MakeGenericType.

+0

Chciałbym stub metoda rodzajowa, w oparciu o typ. Ale jeśli zrobię to za pomocą refleksji, a następnie odgadnę wygenerowany, zrozumieją, że nie będzie to, co chcę. Zgaduję, że to niemożliwe? Albo to jest? Stub ogólny sposób dla wszystkich typów na liście ... –

+1

@Stephane: Trudno jest dokładnie określić, co próbujesz zrobić. Proponuję zadać nowe pytanie z większą ilością szczegółów. –

+0

Uwaga: możesz uzyskać "Niejednoznaczne dopasowanie w rozdzielczości metody" na 'GetMethod()'. Dzieje się tak, gdy metoda, którą próbujesz uzyskać, ma pewne przeciążenia. Musisz więc określić, który z nich chcesz, używając 'GetMethod (" Name ", new Type [] {arguments})' – cvsguimaraes