Замените вложенный ForEach на Select, если применимо - PullRequest
1 голос
/ 26 августа 2009

Можно ли заменить использование метода ForEach() на Select() или что-то еще, чтобы написать следующий код в одну строку с вложенными методами расширения? ИЛИ может быть есть другие способы улучшить алгоритм?

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

Загружает все классы из сборок в path, которые реализуют IFoo, и добавляет их к Dictionary<string, Type>, где строка IFoo.Name

Ответы [ 2 ]

3 голосов
/ 26 августа 2009
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());
3 голосов
/ 26 августа 2009

Я не вижу здесь никакой необходимости в промежуточном List - вы можете просто сделать это:

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, прежде чем пытаться создать его экземпляр.

...