2009-08-25 7 views
1

Est-il possible de remplacer l'utilisation de la méthode ForEach() par Select() ou autre chose pour écrire le code suivant dans une chaîne avec des méthodes d'extension imbriquées? OU peut-être existe-t-il d'autres façons d'améliorer l'algorithme?Remplacer ForEach imbriqué avec Sélectionner si applicable

var list = new List<IStatementParser>(); 

System.IO.Directory.GetFiles(path, "*.dll") 
    .ForEach(f => System.Reflection.Assembly.LoadFrom(f) 
     .GetTypes() 
     .Where(t => !t.IsInterface && typeof(IFoo).IsAssignableFrom(t)) 
     .ForEach(t => list.Add((IFoo)Activator.CreateInstance(t)))); 

return list.ToDictionary(k => k.Name, v => v.GetType()); 

Il charge toutes les classes d'ensembles en path qui implémente IFoo et les ajoute à Dictionary<string, Type> où la chaîne est IFoo.Name

Répondre

3
var foos = 
    from dllFile in Directory.GetFiles(path, "*.dll") 
    from type in Assembly.LoadFrom(dllFile).GetTypes() 
    where !type.IsInterface && typeof(IFoo).IsAssignableFrom(type) 
    select (IFoo) Activator.CreateInstance(type); 

return foos.ToDictionary(foo => foo.Name, foo => foo.GetType()); 
+1

Vous avez besoin d'un paramètre foo => foo.GetType() en tant que délégué de la valeur dans l'appel ToDictionary. Sinon, une excellente réponse. –

+0

Je n'ai besoin que de clarifier l'utilisation de 'let' ci-dessus et je suis prêt à accepter votre réponse. Et btw, je n'ai pas besoin de Dictionary , j'ai besoin de Dictionary où Type = IFoo (j'ai édité le post initial) - car ce dictionnaire sera utilisé par FooFactory pour créer une instance de IFoo par demande, cela peut ne pas arriver du tout, dans la session en cours. – abatishchev

+0

Modifié pour inclure l'appel .GetType(). La clause let dans la réponse de @ Pavel est un truc de style - vous n'avez pas besoin de l'avoir, mais il peut le percevoir comme plus clair. –

3

Je ne vois pas la nécessité d'un intermédiaire List tout ici - vous pouvez juste faire ceci:

return (from dll in Directory.GetFiles(path, "*.dll") 
     let asm = Assembly.LoadFrom(dll) 
     from t in asm.GetTypes() 
     where !t.IsInterface && typeof(IFoo).IsAssignableFrom(t) 
     select (IFoo)Activator.CreateInstance(t) 
     ).ToDictionary(foo => foo.Name, foo => foo.GetType()) 

Par ailleurs, vous pouvez également vérifier si un type est abstract avant d'essayer de instancier.

+0

Pourriez-vous s'il vous plaît décrire ce que vous utilisez 'let'? Bryan Watts ci-dessous n'est pas – abatishchev

+0

C'est une chose commodité/lisibilité, pas strictement nécessaire. –