我不能通过Expression.Property访问我的对象的属性,除非fed表达式的类型是强类型的

时间:2013-08-11 03:43:31

标签: c#

我得到以下代码的例外:

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"和相关对象 - 它无法提前知道。

我可以做些什么来解决我的异常?

2 个答案:

答案 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();