据此:Adding properties and methods to an ExpandoObject, dynamically!,
...当您想要添加动态命名的属性时,您可以使用 expando 对象作为您的值持有者,并将其转换为 IDictionary。
例子
dynamic myobject = new ExpandoObject();
IDictionary<string, object> myUnderlyingObject = myobject;
myUnderlyingObject.Add("IsDynamic", true); // Adding dynamically named property
Console.WriteLine(myobject.IsDynamic); // Accessing the property the usual way
这是经过测试的,将在控制台屏幕上打印出“true”。
当然,在你的情况下,你的底层对象必须从另一个类继承,这个例子只是为了给你一个潜在的自定义实现的想法。
也许在您的类实现中包含一个 expando 对象,并将对 tryget 和 tryset 的调用重定向到您的类中的 expando 对象的实例?
更新
如果您的基类派生自 DynamicObject(这意味着您可以覆盖所有 TrySet/Get/Invoke 方法),那么您也可以在内部使用字典。在 try get/set 覆盖中,您可以执行任何您想要的事件触发,并将设置委托给内部字典。
要添加新属性(或删除现有属性),您可以覆盖 TryInvoke。例如,当方法名称是“AddProperty”并且有一个字符串类型的参数时,您将在字典中添加一个带有参数名称的新项目。同样,您可以动态定义“RemoveProperty”等。您甚至不需要 expando 对象。
class MyBaseClass: DynamicObject
{
// usefull functionality
}
class MyClass: MyBaseClass
{
Dictionary<string, object> dynamicProperties = new Dictionary<string, object>();
override bool TryGetMember(...)
{
// read the value of the requested property from the dictionary
// fire any events and return
}
override bool TrySetMember(...)
{
// set the value of the requested property to the dictionary
// if the property does not exist,
// add it to the dictionary (compile time dynamic property naming)
// fire any events
}
override bool TryInvoke(...)
{
// check what method is requested to be invoked
// is it "AddProperty"??
// if yes, check if the first argument is a string
// if yes, add a new property to the dictionary
// with the name given in the first argument (runtime dynamic property naming)
// if there is also a second argument of type object,
// set the new property's value to that object.
// if the method to be invoked is "RemoveProperty"
// and the first argument is a string,
// remove from the Dictionary the property
// with the name given in the first argument.
// fire any events
}
}
// USAGE
static class Program
{
public static void Main()
{
dynamic myObject = new MyClass();
myObject.FirstName = "John"; // compile time naming - TrySetMember
Console.WriteLine(myObject.FirstName); // TryGetMember
myObject.AddProperty("Salary"); // runtime naming (try invoke "AddProperty" with argument "Salary")
myObject.Salary = 35000m;
Console.WriteLine(myObject.Salary); // TryGetMember
myObject.AddProperty("DateOfBirth", new DateTime(1980,23,11)); // runtime naming (try invoke "AddProperty" with fisrt argument "DateOfBirth" and second argument the desired value)
Console.WriteLine(myObject.DateOfBirth); // TryGetMember
myObject.RemoveProperty("FirstName"); // runtime naming (try invoke "RemoveProperty" with argument "FirstName")
Console.WriteLine(myObject.FirstName); // Should print out empty string (or throw, depending on the desired bahavior) because the "FirstName" property has been removed from the internal dictionary.
}
}
当然,正如我所说,这只有在您的基类派生自 DynamicObject 时才有效。