C # DynamicObject динамические свойства

Предполагая, что я не могу использовать ExpandoObject и мне нужно свернуть свое собственное так:

class MyObject : DynamicObject {
    dictionary<string, object> _properties = dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        string name = binder.Name.ToLower();

        return _properties.TryGetValue(name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value) {
        _properties[binder.Name.ToLower()] = value;

        return true;
    }
}

и дальше вниз по иерархии классов у меня есть

class MyNewObject : MyObject {
    public string Name {
        get {
            // do some funky stuff
        }
        set {
            // ditto
        }
    }
}

что довольно приятно, так как теперь я могу сделать следующее:

dynamic o = MyNewObject();

o.Age = 87;     // dynamic property, handled by TrySetMember in MyObject
o.Name = "Sam"; // non dynamic property, handled by the setter defined in MyNewObject

Но вышеизложенное предполагает, что я знаю свойства (например, возраст, имя) во время компиляции.

Предположим, я не знаю, какими они будут до времени выполнения.

Как я могу изменить вышеперечисленное для поддержки свойств, которые я буду знать только во время выполнения?

По сути, я думаю, что я спрашиваю, как я могу вызвать код, который напрямую вызывает TrySetMember, чтобы он либо создал новое свойство, либо использовал метод получения / установки, если он был определен.

Final Solution as follows :-

using System.Dynamic;
using Microsoft.CSharp.RuntimeBinder;
using System.Runtime.CompilerServices;

class MyObject : DynamicObject {
    Dictionary<string, object> _properties = new Dictionary<string, object>();

    public object GetMember(string propName) {
        var binder = Binder.GetMember(CSharpBinderFlags.None,
              propName, this.GetType(),
              new List<CSharpArgumentInfo>{
                       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)});
        var callsite = CallSite<Func<CallSite, object, object>>.Create(binder);

        return callsite.Target(callsite, this);
    }

    public void SetMember(string propName, object val) {
        var binder = Binder.SetMember(CSharpBinderFlags.None,
               propName, this.GetType(),
               new List<CSharpArgumentInfo>{
                       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null),
                       CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)});
        var callsite = CallSite<Func<CallSite, object, object, object>>.Create(binder);

        callsite.Target(callsite, this, val);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result) {
        string name = binder.Name.ToLower();

        return _properties.TryGetValue(name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value) {
        _properties[binder.Name.ToLower()] = value;

        return true;
    }
}

Ответы на вопрос(2)

Ваш ответ на вопрос