2010-05-27 20 views
6

Ho diversi oggetti su modelli che tutta implementare la stessa interfaccia:C# determinare tipo generico

OSSIA

MyObject<datatype1> obj1; 
MyObject<datatype2> obj2; 
MyObject<datatype3> obj3; 

voglio memorizzare questi oggetti in un elenco ... Penso che dovrei farlo in questo modo:

private List<MyObject<object>> _myList; 

Allora voglio creare una funzione che prende 1 parametro, essendo un tipo di dati , per vedere se un oggetto che utilizza quel tipo di dati esiste nel mio elenco .... in qualche modo senza tracce su come procedere. In pseudo codice sarebbe:

public bool Exist(DataType T) 
{ 
    return (does _myList contain a MyObject<T>?); 
} 

qualche chiarimento ....

mio interfaccia è IMyObject<T>, i miei oggetti sono MyObject<T>. Ho una nuova classe MyObjectManager che ho bisogno di avere un elenco di MyObject<T> memorizzato all'interno. Ho bisogno di una funzione per verificare se esiste un MyObject<T> nell'elenco. Il tipo T sono tipi di dati che sono stati generati automaticamente utilizzando T4 .... classi POCO dal mio modello di dati Entity.

+0

Cosa se contiene un 'MyObject 'e' U' eredita 'T'? – SLaks

+0

Bene la mia U viene generata automaticamente usando le classi T4 e EF POCO. –

+0

Le classi si ereditano l'una con l'altra? – SLaks

risposta

6

si può fare una funzione generica:

public bool Exists<T>() where T : class { 
    return _myList.OfType<MyObject<T>>().Any(); 
} 

Si noti che questo richiede che si sa T a tempo di compilazione.

Se hai a disposizione solo un oggetto System.Type in fase di esecuzione, sarà necessario utilizzare la riflessione:

public bool Exists(Type t) { 
    var objectOfT = typeof(MyObject<>).MakeGenericType(t); 

    return _myList.Any(o => o.GetType() == objectOfT); 
} 

Si noti, tuttavia, che un List<MyObject<object>>non può tenere unaMyObject<SomeType>.
È necessario modificare l'elenco su List<object> oppure eseguire l'implementazione MyObject o ereditare un tipo non generico e rendere l'elenco contenente tale tipo.

+0

La mia classe che memorizza l'elenco non avrà un tipo generico, tuttavia la T in MyObject è nota al momento della compilazione e lo spazio dei nomi per questi oggetti viene fatto riferimento in questa classe. Quando provo il tuo primo esempio dice che il tipo T deve essere un tipo di riferimento per poterlo usare come parametro. Voglio che T sia un tipo generico così posso passare qualsiasi tipo di dati, sia esso int, string, ecc. –

+0

Devi aggiungere un 'dove T: class' contstraint, per abbinare il vincolo in' MyObject'. – SLaks

+0

Capito ... doveva aggiungere bool pubblico Esiste () dove T: class .... grazie! –

0

Poiché tutti implementano la stessa interfaccia, anziché lanciarli sull'oggetto e chiamare GetType (che può essere costoso) perché non aggiungere una proprietà all'interfaccia chiamata nome di classe (o qualcosa del genere)? Quindi puoi usare il linq per afferrare quella proprietà. E non dimenticare using System.Linq

using System.Linq; 

public bool Exist(List<IMyInterface> objects, IMyInterface typeToCheck) 
{ 
    return objects.Any(t => t.ObjectName == typeToCheck.ObjectName); 
} 
+0

La mia interfaccia è IMyInterface

1

Che ne dici di un metodo di estensione?

public static bool HasAny(this IEnumerable source, Type type) { 
    foreach (object item in source) 
     if (item != null && item.GetType().Equals(type)) 
      return true; 

    return false; 
} 

Usage:

bool hasDataType1 = myList.HasAny(typeof(MyObject<datatype1>)); 

Si noti che se non si vuole avere a digitare le typeof(...) - vale a dire, se si desidera che fondamentalmente la vostra Exist metodo per solo cura di oggetti di tipo MyObject<T>, mi piacerebbe andare con qualcosa come la risposta di SLaks:

public static bool Exist<T>(this IEnumerable source) { 
    return source.OfType<MyObject<T>>().Any(); 
} 

Inoltre, SLaks è giusto che si r eally non può avere un List<MyObject<object>> pieno di oggetti diversi dal tipo MyObject<object> o qualche classe derivata (e MyObject<datatype1>, ecc.do non derivano da MyObject<object> - i generici non funzionano in questo modo).

Un altro modo potrei suggerire a risolvere l'intera questione "non è possibile ottenere il tipo di una classe generica utilizzando un oggetto System.Type senza usare riflessione" sarebbe questo: Fai la tua MyObject<T> implementare un'interfaccia non generico, come questo:

public interface IMyObject { 
    Type DataType { get; } 
} 

public class MyObject<T> : IMyObject<T>, IMyObject { 
    public Type DataType { 
     get { return typeof(T); } 
    } 
} 

Allora la vostra lista potrebbe essere una (l'interfaccia non generica) List<IMyObject> e il metodo di Exist potrebbe essere la seguente:

public static bool Exist<T>(this IEnumerable source, Type type) { 
    return source.OfType<IMyObject>().Any(x => x.DataType.Equals(type)); 
}