2013-08-14 2 views
20

Ho un'interfacciaControllare se un tipo implementa un'interfaccia generica senza considerare gli argomenti di tipo generico

public interface MyInterface<TKey, TValue> 
{ 
} 

implementazioni sono irrilevanti. Ora voglio verificare se un determinato tipo è un'implementazione di tale interfaccia. Questo metodo non riesce per

public class MyClass : MyInterface<int, string> 
{ 
} 

Ma non so come eseguire il controllo.

public void CheckIfTypeImplementsInterface(Type type) 
{ 
    var result1 = typeof(MyInterface<,>).IsAssignableFrom(type); --> false 
    var result2 = typeof(MyInterface<int,string>).IsAssignableFrom(type); --> true 
} 

Che cosa devo fare affinché result1 sia vero?

+0

Avete considerato di creare un'interfaccia 'MyInterface' e avete' MyInterface : MyInterface'? –

risposta

33

Per quanto ne so, l'unico modo per farlo è quello di ottenere tutte le interfacce e vedere se la definizione generica corrisponde al tipo di interfaccia richiesto.

bool result1 = type.GetInterfaces() 
    .Where(i => i.IsGenericType) 
    .Select(i => i.GetGenericTypeDefinition()) 
    .Contains(typeof(MyInterface<,>)); 

EDIT: Come Jon fa notare nei commenti, si potrebbe anche fare:

bool result1 = type.GetInterfaces() 
    .Where(i => i.IsGenericType) 
    .Any(i => i.GetGenericTypeDefinition() == typeof(MyInterface<,>)); 
+4

Puoi cambiare i tuoi ultimi due in: '.Any (i => i.GetGenericTypeDefinition() == typeof (MyInterface <,>))' –

2

In generale, tale comportamento è richiesto solo nei casi in cui un interfaccia contiene alcune funzionalità che non dipende dalla parametri di tipo generico. Se si ha il controllo delle interfacce, la soluzione migliore consiste nel far ereditare le parti dipendenti dal tipo da una parte non dipendente dal tipo. Per esempio, se non esistessero le interfacce di raccolta esistenti, si potrebbe definirli qualcosa di simile:

interface ICountable 
    { CollectionAttribute Attributes {get;} int Count {get;} } 
interface ICollection<T> : IEnumerable<T> ICountable 
    { ... and other stuff ... } 

avuto una cosa simile stato fatto con ICollection, quindi codice che si aspettava un IEnumerable<Animal> ma abbiamo ottenuto un oggetto di tipo CatList che implementa semplicemente IList<Cat> non avrebbe alcun problema usando il membro Count di quell'oggetto (si noti che List<Animal> implementa lo ICollection non generico, ma altre implementazioni IList<Animal> potrebbero non).

Come è, se sei bloccato con il compito di contenere codice in qualche modo trovare il metodo di ICollection<Cat>Count quando si aspetta un IEnumerable<Animal>, può essere utile per costruire qualcosa di simile a un Dictionary<Type, Func<IEnumerable<Animal>, int> in modo che una volta che hai trovato che CatList implementa ICollection<Cat>.Count è possibile costruire un delegato a un metodo che invierà il suo argomento a ICollection<Cat>, chiamare Count su di esso e restituirne il risultato. Se hai un tale dizionario, se ti viene dato un altro CatList, potrai semplicemente richiamare il delegato dal dizionario.

+0

Totalmente aggree, ma nel mio caso voglio solo eseguire un controllo di base in un attributo ' [CustomAttribute (typeof (ClassName))] 'e ho bisogno di ClassName per implementare l'interfaccia. Più in codice, conosco entrambi gli attributi generici e posso usare reflection per creare una nuova istanza di ClassName –