2009-08-25 9 views
1

メソッドForEach()Select()などと置き換えて、ネスト拡張メソッドを使用して次のコードを1つの文字列に書き込むことはできますか?または、アルゴリズムを改善する別の方法がありますか?ネストされたForEachを置換する場合は選択

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()); 

それはIFooを実装し、文字列がIFoo.Name

答えて

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

ToDictionary呼び出しの値デリゲートとしてfoo => foo.GetType()パラメータが必要です。そうでなければ、素晴らしい答えです。 –

+0

上記の「let」の使用方法を明確にするだけで、私はあなたの答えを受け入れる準備ができています。そして、この辞書はFooFactoryによってIFooのインスタンスを作成するために使用されるため、Dictionary 、Dictionary 型= IFoo(私は最初の投稿を編集しました)が必要です。現在のセッションでは、まったく発生しない可能性があります。 – abatishchev

+0

.GetType()呼び出しを含むように編集されました。 @パベルの答えのlet節は、スタイルのものです。あなたはそれを持つ必要はありませんが、彼はそれをより明確に認識しているかもしれません。 –

3

である私は全然ここで中間Listの必要性を見ないDictionary<string, Type>に追加することpathにアセンブリからすべてのクラスをロードする - あなただけ行うことができますこの:

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()) 

ところで、あなたはまたタイプがそれをインスタンス化しようとする前にabstractであるかどうかを確認したい場合があります。

+0

「let」を使用するための説明を教えてください。以下のブライアンワットは – abatishchev

+0

です。それは便利/可読性のものですが、厳密には必要ありません。 –