В соответствии с этим: Добавление свойств и методов в ExpandoObject, динамически! ,
... вы можете использовать объект 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 в вашем классе?
UPDATE
Если ваш базовый класс является производным от DynamicObject (то есть вы можете переопределить все методы TrySet / Get / Invoke), вы также можете использовать словарь для внутреннего использования. В переопределениях try get / set вы выполняете любое событие, которое хотите, и делегируете настройку во внутренний словарь.
Чтобы добавить новое свойство (или удалить существующее), вы можете переопределить TryInvoke. Когда имя метода, например, «AddProperty» и есть один аргумент типа string, вы добавляете в свой словарь новый элемент с именем аргумента. Точно так же вы бы динамически определяли «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.