我有一个基于抽象Device
类的类层次结构。所有设备的存储库看起来有点像这样:
class Hardware
{
public readonly DeviceCollection<Switch> Switches = ...;
public readonly DeviceCollection<Light> Lights = ...;
}
在哪里DeviceCollection
实现IEnumerable<T> where T : Device
。
我需要枚举所有设备,而我目前糟糕的代码就是这样做的
protected override IEnumerator<Device> enumerate()
{
foreach (var light in Lights)
{
yield return light;
}
foreach (var @switch in Switches)
{
yield return @switch;
}
}
这并不可靠,因为有时我会添加一些新的硬件,一个新DeviceCollection
的并且很容易忘记在上面添加新的迭代。所以我想一些反思会有所帮助 - 懒惰地建立一个DeviceCollection
字段列表并运行它。但是该列表的声明会是什么样子?
private List<DeviceCollection<T>> _collections;
不编译。也没有
private List<DeviceCollection> _collections;
如何声明此列表?
推论:Tim S 的回答——IEnumerable 是协变的——解决了我的直接问题。剩下的一个小故障(我敢肯定有一个更简单的解决方案!)是如何进行反射。这是我的丑陋丑陋的黑客:
_collections = new List<IEnumerable<Device>>();
var fields = GetType().GetFields( BindingFlags.Instance | BindingFlags.Public );
foreach (var field in fields)
{
if (field.FieldType.Name.Contains( "DeviceCollection" ))
{
_collections.Add( (IEnumerable<Device>)field.GetValue(this) );
}
}
这是因为测试
if (field.FieldType == typeof(DeviceCollection<>)
不起作用。