我可以';t通过Expression.property访问对象的属性,除非馈送表达式的类型是强类型的
本文关键字:表达式 强类型 类型 属性 我可以 通过 Expression 对象 访问 property | 更新日期: 2023-09-27 18:27:16
我得到以下代码的异常:
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"
和相关对象——这是不可能提前知道的。
我可以做些什么来修复我的异常?
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();
这似乎有效。。。
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();