C# 我能';t通过Expression.property访问我的对象上的属性,除非fed表达式的类型是强类型

C# 我能';t通过Expression.property访问我的对象上的属性,除非fed表达式的类型是强类型,c#,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

我得到以下代码的一个异常:

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);
}
公共类内部类
{
公共对象值{get;set;}
}
公共舱外舱
{
//如果我将此属性的类型更改为“InnerClass”,则会删除异常
公共对象内部{get;set;}
}
私有静态void SmallSandbox()
{
var outer=新的OuterClass()
{
内部=新的内部类()
{
值=2
}
};
var p=表达式参数(typeof(OuterClass),“p”);
Func e=表达式.Lambda(
Expression.Property(Expression.Property(p,“内部”),“值”),
P
).Compile();
var a=new[]{outer}.Select(e.First();
控制台写入线(a);
}
公共对象内部{get;set;}
更改为
公共内部类内部{get;set;}
将删除异常。这不是一个选项,因为我让我的程序的使用者最终提供属性名
“Value”
和相关对象-它无法提前知道


如何修复我的异常?

内部
被声明为
对象
。显然,
对象
不包含
属性。在尝试访问该属性之前,需要将该表达式“转换”为预期类型。这相当于向表达式添加强制转换

Func<OuterClass, object> e = Expression.Lambda<Func<OuterClass, object>>(
    Expression.Property(
        Expression.Convert(Expression.Property(p, "Inner"), typeof(InnerClass)),
        "Value"
    ),
    p
).Compile();
Func e=Expression.Lambda(
表达式.属性(
Expression.Convert(Expression.Property(p,“内部”),typeof(InnerClass)),
“价值”
),
P
).Compile();

内部
被声明为
对象
。显然,
对象
不包含
属性。在尝试访问该属性之前,需要将该表达式“转换”为预期类型。这相当于向表达式添加强制转换

Func<OuterClass, object> e = Expression.Lambda<Func<OuterClass, object>>(
    Expression.Property(
        Expression.Convert(Expression.Property(p, "Inner"), typeof(InnerClass)),
        "Value"
    ),
    p
).Compile();
Func e=Expression.Lambda(
表达式.属性(
Expression.Convert(Expression.Property(p,“内部”),typeof(InnerClass)),
“价值”
),
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();
使用Microsoft.CSharp.RuntimeBinder;
var p=表达式参数(typeof(OuterClass),“p”);
var binder=binder.GetMember(CSharpBinderFlags.None,“Value”,outer.Inner.GetType(),new[]{CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null)});
var e=表达式.Lambda(
Expression.Dynamic(binder,typeof(object),Expression.Property(p,“Inner”),
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();
使用Microsoft.CSharp.RuntimeBinder;
var p=表达式参数(typeof(OuterClass),“p”);
var binder=binder.GetMember(CSharpBinderFlags.None,“Value”,outer.Inner.GetType(),new[]{CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None,null)});
var e=表达式.Lambda(
Expression.Dynamic(binder,typeof(object),Expression.Property(p,“Inner”),
P
).Compile();

听起来像你想要一个接口对我来说就像你想要一个接口如果你事先不知道类型,你将不得不求助于生成使用反射的表达式来确定类型和它有什么属性。是否可以使用像Linq到EF这样的技术,它的树上禁止某些表达?我不能肯定。如果您指的是在EF查询中使用反射,恐怕这是不可能的。另一方面,您不应该关心生成适用于任何类型的通用表达式。在这些情况下,生成专门用于所使用类型的表达式会更容易。在这些情况下,创建泛型工厂方法会很有帮助。如果您事先不知道类型,您将不得不求助于生成使用反射来确定类型及其属性的表达式。是否可以使用类似Linq to EF的技术,它的树上禁止某些表达?我不能肯定。如果您指的是在EF查询中使用反射,恐怕这是不可能的。另一方面,您不应该关心生成适用于任何类型的通用表达式。在这些情况下,生成专门用于所使用类型的表达式会更容易。在这些情况下,创建一个通用工厂方法会很有帮助。