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());
}
}
精彩评论