我正在探索.NET 4.0中的DynamicObject模型 . 应用程序是通过某种text / xml文件描述对象的应用程序,程序必须在读取该文件时创建对象 .
使用DynamicObject,我们可以轻松添加成员,因为我们知道成员的名称是先验的 . 但是,如果我们甚至不知道要添加的成员的名称呢?有没有办法让这种动态变化?
例如,假设我需要使用成员'Property1','Property2'创建一个对象,使用'PropertyA'创建另一个对象,并使用text / XML文件描述'PropertyB' . 如何根据此信息动态创建对象?
UPDATE 我从这篇文章中得到了一些想法:http://www.codeproject.com/KB/cs/dynamicincsharp.aspx
这个实现允许我做类似以下的事情:
dynamic d = new PFDynamicChannel();
PFCouplings c = ((PFChannel)d).Coupling;
d.NewProperty = "X";
我不想使用字典的原因是使用TryGetMember和TrySetMember方法,我可以覆盖,我可以在其中引发对程序至关重要的事件 .
这样,我可以继承基类(PFChannel),但我也可以动态添加成员 . 但是,我的问题是我不会知道新的属性名称,直到运行时 . 而且,我实际上并不认为动态对象允许我动态添加新属性 . 如果是这种情况,我如何利用ExpandoObject来提供这种能力呢?
5 回答
如果你只需要这样做,你应该看ExpandoObject . 如果你需要这样做并且仍然使用
DynamicObject
,你需要编写代码来记住属性值,基本上......你可以用嵌入式ExpandoObject
来做 .之后我不清楚你想用这个对象做什么 - 你确定你需要动态打字吗?
Dictionary<string, object>
实际上会更糟吗?这取决于以后基本上会消耗该对象的内容 .根据这个:Adding properties and methods to an ExpandoObject, dynamically!,
...您可以使用expando对象作为值持有者,并在想要添加动态命名属性时将其强制转换为IDictionary <string,object> .
例
这已经过测试,并将在控制台屏幕上打印出“true” .
当然,在您的情况下,您的底层对象必须从另一个类继承,这个示例只是为了让您了解潜在的自定义实现 .
也许在类实现中包含一个expando对象,并将调用重定向到tryget和tryset到类中expando对象的实例?
UPDATE
如果您的基类派生自DynamicObject(意味着您可以覆盖所有TrySet / Get / Invoke方法),那么您也可以在内部使用字典 . 在try get / set覆盖中,您可以执行任何您想要的事件,并将设置委托给内部字典 .
要添加新属性(或删除现有属性),您可以覆盖TryInvoke . 例如,当mothod名称是“AddProperty”并且有一个类型为string的参数时,您将在字典中添加一个带有参数名称的新项 . 类似地,您将动态定义“RemoveProperty”等 . 您甚至不需要expando对象 .
当然,正如我所说,只有你的基类派生自DynamicObject时才会有效 .
在这种情况下,我不确定您是否要使用动态对象 .
c#中的dynamic允许你做以下事情:
如果您使用ExpandoObject,您可以:
这两个都允许您使用propertyname,就好像它在编译时实际存在一样 . 在你的情况下,你赢了't need to use this syntax at all, so I'我不确定它会给你任何好处 . 相反,为什么不使用
Dictionary<string, object>
,并且:因为
Dictionary<string,object>
基本上是一个expando对象 - 但它支持不同的语法 . 是的,我没有在其他代码或绑定/ etc中使用它,那么这基本上是正确的 .与Thanasis Ioannidis相关的答案有关变体“如果您的基类派生自DynamicObject”,有一种更简单的方法,只需在“MyClass”类中添加方法AddProperty,如下所示:
然后你可以使用
您不需要任何覆盖“TryInvoke” .
dynamic
类型基本上实现为Property Bag . 这意味着它的键(属性名称)和对象的字典(这里是非类型安全的方式) . 如果您可以直接访问此词典,我就不会使用,但您可以自己使用词典 .该死的,Jon Skeet更快:(