使用ISomething </t>的所有实现填充HashSet <t>

时间:2011-04-08 07:48:38

标签: c# .net

我要求一个更顺畅和更好的方法来做这个(和/或更正,如果我在这里错了),

HashSet<ISomething> itemRows;

List<ISomething> PopulateItemRows()
{
    itemRows = new HashSet<ISomething>();
    itemRows.UnionWith(new SomeType1().Collection());
    itemRows.UnionWith(new SomeType2().Collection());
    itemRows.UnionWith(new SomeType3().Collection());
    itemRows.UnionWith(new SomeType4().Collection());
    return itemRows.ToList();
}

SomeTypeXX都实现了ISomething。

最好的当然是避免明确包括类型。 可能存在新实现的情况,并且此方法无法更新。

3 个答案:

答案 0 :(得分:2)

如果您想要一种通用方法来查找实现ISomething的所有类型:

var somethingTypes = typeof(ISomething)
    .Assembly
    .GetTypes() 
    .Where(t => t.IsClass && !t.IsAbstract && t.GetInterfaces().Any(i => i == typeof(ISomething))

foreach (var t in somethingTypes)
{
    var o = Activator.CreateInstance(t);
    var mi = (IEnumerable<ISomething>)t.GetMethod("Collection");
    if (mi != null)
    {
        var items = .Invoke(o, null);
        itemRows.UnionWith(items); 
    }
}

该代码假定实现ISomething的所有类型都与接口位于同一个程序集中。

更新:根据Martins回答添加了一些健全性检查

答案 1 :(得分:1)

我从这开始:

...
List<ISomething> instances = new List<ISomething>({new SomeType1(), new SomeType2(),...});
...
List<ISomething> PopulateItemRows()
{
    itemRows = new HashSet<ISomething>();
    foreach(ISomething instance in instances)
    {
        itemRows.UnionWith(instance.Collection());
    }
}

答案 2 :(得分:0)

我不知道你的代码是否真的像这样,因为ISomething看起来有点奇怪。无论如何,这是一个基于反思的解决方案。

interface ISomething {
  IEnumerable<ISomething> Collection();
}

List<ISomething> PopulateItemRows() {
  var itemRows = new HashSet<ISomething>();
  var constructorInfos = Assembly.GetExecutingAssembly().GetTypes()
    .Where(
      type => type.IsClass
      && !type.IsAbstract
      && typeof(ISomething).IsAssignableFrom(type)
    )
    .Select(type => type.GetConstructor(Type.EmptyTypes))
    .Where(ci => ci != null);
  foreach (var constructorInfo in constructorInfos) {
    var something = (ISomething) constructorInfo.Invoke(null);
    itemRows.UnionWith(something.Collection());
  }
}