我得到以下代码的例外:
public class InnerClass
{
public object Value { get; set; }
}
public class OuterClass
{
// If I change the type of this property to "InnerClass" the exception is removed
public object Inner { get; set; }
}
private static void SmallSandbox()
{
var outer = new OuterClass()
{
Inner = new InnerClass()
{
Value = 2
}
};
var p = Expression.Parameter(typeof(OuterClass), "p");
Func<OuterClass, object> e = Expression.Lambda<Func<OuterClass, object>>(
Expression.Property(Expression.Property(p, "Inner"), "Value"),
p
).Compile();
var a = new[] { outer }.Select(e).First();
Console.WriteLine(a);
}
将public object Inner { get; set; }
更改为public InnerClass Inner { get; set; }
会删除该异常。这不是一个选项,因为我让我的程序的消费者最终提供属性名称"Value"
和相关对象 - 它无法提前知道。
我可以做些什么来解决我的异常?
答案 0 :(得分:2)
Inner
被声明为object
。显然,object
不包含Value
属性。在尝试访问该属性之前,需要将该表达式“转换”为期望的类型。这相当于向表达式添加强制转换。
Func<OuterClass, object> e = Expression.Lambda<Func<OuterClass, object>>(
Expression.Property(
Expression.Convert(Expression.Property(p, "Inner"), typeof(InnerClass)),
"Value"
),
p
).Compile();
答案 1 :(得分:1)
这似乎有用......
using Microsoft.CSharp.RuntimeBinder;
var p = Expression.Parameter(typeof(OuterClass), "p");
var binder = Binder.GetMember(CSharpBinderFlags.None, "Value", outer.Inner.GetType(), new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
var e = Expression.Lambda<Func<OuterClass, object>>(
Expression.Dynamic(binder, typeof(object) ,Expression.Property(p, "Inner")),
p
).Compile();