Наконец-то я смог сделать это, используя механизм связывания C #.(Я полагаю, что это возможно сделать с помощью более простой реализации связующего, но я не смог написать рабочую - вероятно, написать «простую» реализацию уже довольно сложно).
using Microsoft.CSharp.RuntimeBinder;
private class TestClass
{
public String Prop { get; set; }
}
private static Func<object, object> BuildDynamicGetter(Type targetType, String propertyName)
{
var rootParam = Expression.Parameter(typeof(object));
var propBinder = Microsoft.CSharp.RuntimeBinder.Binder.GetMember(CSharpBinderFlags.None, propertyName, targetType, new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
DynamicExpression propGetExpression = Expression.Dynamic(propBinder, typeof(object),
Expression.Convert(rootParam, targetType));
Expression<Func<object, object>> getPropExpression = Expression.Lambda<Func<object, object>>(propGetExpression, rootParam);
return getPropExpression.Compile();
}
static void Main(string[] args)
{
dynamic root = new TestClass { Prop = "StatValue" };
Console.Out.WriteLine(root.Prop);
var dynGetter = BuildDynamicGetter(root.GetType(), "Prop");
Console.Out.WriteLine(dynGetter(root));
root = new System.Dynamic.ExpandoObject();
root.Prop = "ExpandoValue";
Console.WriteLine(BuildDynamicGetter(root.GetType(), "Prop").Invoke(root));
Console.Out.WriteLine(root.Prop);
Console.In.ReadLine();
}
Вывод:
StatValue
StatValue
ExpandoValue
ExpandoValue