2009-06-26 6 views
0

J'ai une liste d'interface qui stocke une variété d'objets dérivés de cette interface. Je voudrais écrire une fonction où l'appelant spécifie le type à extraire. Je l'ai essayé ceci:Extrait les éléments dérivés d'une liste d'éléments de base

List<IParts> PartList; 

...

public List<IPart> Fetch(Type PartType) 
{ 
    return this.PartList.OfType<PartType>().Cast<IPart>().ToList(); 
} 

Mais il n'aime pas un type passé. Aucune suggestion?

Répondre

2

Si vous devez supporter différents types lors de l'exécution (plutôt que au moment de la compilation avec les génériques):

public List<IPart> Fetch(Type PartType) 
{ 
    if (!typeof(IPart).IsAssignableFrom(PartType)) 
    { 
     throw new ArgumentOutOfRangeException("PartType", "Must derive from IPart"); 
    } 
    return this.PartList.Where(i => i != null && PartType.IsAssignableFrom(i.GetType())).ToList(); 
} 
+0

Nice - certainement un peu plus simple que d'utiliser la réflexion pour obtenir la méthode générique. Probablement plus efficace pour les petites listes et moins efficace pour les grandes listes. Vous pourriez vouloir vérifier la nullité avant d'appeler i.GetType(). –

+0

Là je vais supposer que l'entrée est encore valide. :) –

2

Spécifiez comme un paramètre de type à la place:

public List<IPart> Fetch<T>() where T : IPart 
{ 
    return this.PartList.OfType<T>().Cast<IPart>().ToList(); 
} 

Vous appelleriez comme ceci:

List<IPart> foo = parts.Fetch<Exhaust>(); 

C'est bien si vous connaissez le type de partie à la compilation. Si vous ne le faites pas, vous devrez utiliser la réflexion pour obtenir la méthode OfType() dans Enumerable<T> et créer la méthode générique d'écriture. Quelque chose comme:

private static readonly MethodInfo OfTypeMethod = 
    typeof(Enumerable).GetMethod("OfType"); 

public List<IPart> Fetch(Type partType) 
{ 
    MethodInfo method = OfTypeMethod.MakeGenericMethod(partType); 
    IEnumerable enumerable = (IEnumerable) method.Invoke 
     (null, new object[] { PartList }); 
    return enumerable.Cast<IPart>().ToList(); 
} 
+0

Vous pouvez ajouter un « où T: IPART » restriction générique qui va faites en sorte que vous n'obteniez pas de conversions invalides et d'erreurs logiques –

+0

Ooh, nice - will do. –

Questions connexes