这里的虚构例子。假设我设计了一个名为IODevice的类。这个类已经实现了一个允许我以下列方式使用它的结构:
IODevice dio = new IODevice();
try
{
dio.Pin["IsBirdInCageSensor"].Set();
dio.Pin["KillBird"].Get();
//dio.Pin["NonExistant"].Set(); //exception
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
这里的引脚是数字IO盒中的一系列IO线,可以变为高(1)或低(0)。
我想使用dynamic以下列方式调用它:
dio.Pins.KillBird.Get();
我的IO设备类现在看起来像这样,正如您将注意到的那样,除了使用动态关键字之外,我还没有进一步介绍如何实现动态接口。
class IODevice
{
public IODevice()
{
pin = new PinCollection();
pin.Add(new Pin("IsBirdInCageSensor", 0));
pin.Add(new Pin("KillBird", 1));
}
private PinCollection pin;
public PinCollection Pin { get { return pin; } }
public dynamic Pins { get; private set; }
}
第二个问题是:使用这种设计有哪些缺点? (除了缺乏硬类型检查 - 我无论如何都没有)
答案 0 :(得分:2)
如果您想继续使用现有的PinCollection
类型,那么PinCollection需要实现IDynamicMetaObjectProvider。然后Pins将返回与Pin相同的PinCollection,但因为它被键入为动态将允许obj.Pins.KillBird
语法(并且您的GetMetaObject实现会将其转换为PinCollection上的字典访问)。
如果您可以更改实施,则可以改为使用ExpandoObject类:
private ExpandoObject _pins;
public dynamic Pins { get { return _pins; } }
ExpandoObject基本上是一个已经有一个元对象的字典,它将动态属性访问转换为字典访问。请注意,在这种情况下,您必须摆脱强类型的PinCollection,或找出一些方法来同步这两者:您不希望在两个地方存储不同的引脚数据。