如何创建有意义的动态属性?

时间:2010-03-13 22:53:14

标签: c# dynamic .net-4.0

这里的虚构例子。假设我设计了一个名为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; }
}

第二个问题是:使用这种设计有哪些缺点? (除了缺乏硬类型检查 - 我无论如何都没有)

1 个答案:

答案 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,或找出一些方法来同步这两者:您不希望在两个地方存储不同的引脚数据。