2010-05-14 2 views
9

Ho una funzione con questo codice:Ignora proprietà della raccolta in PropertyInfo

foreach (PropertyInfo propertyInfo in typeof(T).GetProperties()){ 
//SOME CODE 
if (propertyInfo.CanWrite) 
    propertyInfo.SetValue(myCopy, propertyInfo.GetValue(obj, null), null); 
} 

vorrei evitare di controllare "raccolta" proprietà; per fare questo ora ho inserire questo controllo:

if (propertyInfo.PropertyType.Name.Contains("List") 
    || propertyInfo.PropertyType.Name.Contains("Enumerable") 
    || propertyInfo.PropertyType.Name.Contains("Collection")) 
    continue; 

ma, Non mi piace!

Quale è un modo migliore per farlo?

risposta

14

Stavo pensando che si potrebbe desiderare di controllare le interfacce del tipo degli attrezzi di proprietà. (Rimosso interfacce ridondanti, come IList ICollection eredita e ICollection eredita IEnumerable.)

static void DoSomething<T>() 
{ 
    List<Type> collections = new List<Type>() { typeof(IEnumerable<>), typeof(IEnumerable) }; 

    foreach (PropertyInfo propertyInfo in typeof(T).GetProperties()) 
    { 
     if (propertyInfo.PropertyType != typeof(string) && propertyInfo.PropertyType.GetInterfaces().Any(i => collections.Any(c => i == c))) 
     { 
      continue; 
     } 

     Console.WriteLine(propertyInfo.Name); 
    } 
} 

ho aggiunto il codice per non respingere stringa, come si implementa IEnumerable, come pure, e ho pensato che si potrebbe desiderare di mantenere quelli intorno.

Alla luce della ridondanza della lista prima di interfacce di raccolta, può essere più semplice di scrivere il codice come questo

static void DoSomething<T>() 
{ 
    foreach (PropertyInfo propertyInfo in typeof(T).GetProperties()) 
    { 
     if (propertyInfo.PropertyType != typeof(string) 
      && propertyInfo.PropertyType.GetInterface(typeof(IEnumerable).Name) != null 
      && propertyInfo.PropertyType.GetInterface(typeof(IEnumerable<>).Name) != null) 
     { 
      continue; 
     } 

     Console.WriteLine(propertyInfo.Name); 
    } 
} 
+0

+1 Rimosso la mia risposta in quanto è meglio. – GenericTypeTea

+7

IEnumerable <> implementa IEnumerable, non è necessario verificare IEnumerable <> – MaLio

8

Probabilmente verificherei contro IEnumerable.

if ((typeof(string) != propertyInfo.PropertyType) 
    && typeof(IEnumerable).IsAssignableFrom(propertyInfo.PropertyType)) 
{ 
    continue; 
} 
+0

Oh oh, ora ho un problema ... questa condizione vale anche per proprietà stringa. È possibile? –

+0

Risolvo con l'altra soluzione pubblicata. –

+0

@LukePet: le string implementano 'IEnumerable' perché sono raccolte di caratteri. La risposta di Anthony esclude specificamente le stringhe, quindi hai ragione a sceglierne una (e ho aggiornato la mia risposta per seguirne l'esempio). – LukeH

4
bool isCollection = typeof(System.Collections.IEnumerable) 
          .IsAssignableFrom(propertyInfo.PropertyType); 
+0

meglio della risposta giusta – JeffZhnn