开发者

Fill a HashSet<T> with all implementations of ISomething

I asking for a more smooth and nice way to do this (and/or corrections if I'm wrong here),

HashSet<ISomething> itemRows;

List<ISomething> PopulateItemRows()
{
    itemRows = new HashSet<ISomething>();
   开发者_如何学C itemRows.UnionWith(new SomeType1().Collection());
    itemRows.UnionWith(new SomeType2().Collection());
    itemRows.UnionWith(new SomeType3().Collection());
    itemRows.UnionWith(new SomeType4().Collection());
    return itemRows.ToList();
}

SomeTypeXX are all implements the ISomething.

The very best would of course be avoiding the explicit including of types. There can be a scenario of new implementations and this method missed to be updated.


If you want a generic way to find all types implementing 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); 
    }
}

The code assumes that all types implementing ISomething live in the same assembly as the interface.

Update: Added some sanity checks based on Martins answer


I'd start with this:

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


I don't know if you code is truly like this because ISomething looks a bit weird. Anyway, here is a solution based on reflection.

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜