防爆pression树与财产继承导致参数异常 [英] Expression Tree with Property Inheritance causes an argument exception

查看:176
本文介绍了防爆pression树与财产继承导致参数异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面这篇文章:<一个href="http://stackoverflow.com/questions/1937072/how-can-i-write-custom-comparison-definition-for-binary-operator-equal-for-enti">link文字我试图创建一个前pression树引用属性的属性。我的code是这样的:

Following this post: link text I'm trying to create an expression tree that references the property of a property. My code looks like this:

public interface IFoo
{
    void X {get;set;}
}

public interface IBar : IFoo
{
    void Y {get;set;}
}

public interface IFooBarContainer
{
    IBar Bar {get;set;}
}

public class Filterer
{
     //Where T = "IFooBarContainer"
     public IQueryable<T> Filter<T>(IEnumerable<T> collection)
     {
              var argument = Expression.Parameter(typeof (T), "item");

              //...

               //where propertyName = "IBar.X";
               PropertyOfProperty(argument, propertyName); 
     }

        private static MemberExpression PropertyOfProperty(Expression expr, string propertyName)
        {
            return propertyName.Split('.').Aggregate<string, MemberExpression>(null, (current, property) => Expression.Property(current ?? expr, property));
        }
}

我收到异常:

I receive the exception:

System.ArgumentException:实例   物业'X'是没有定义的类型   非洲动物资源局

System.ArgumentException: Instance property 'X' is not defined for type 'IBar'

ReSharper的变成了code在上面的链接进入简明的声明在我的例子。两种形式的方法返回相同的错误。

ReSharper turned the code in the link above into the condensed statement in my example. Both forms of the method returned the same error.

如果我引用 IBar.Y 的方法不会失败。

If I reference IBar.Y the method does not fail.

推荐答案

您尝试访问该物业的没有 IBar.X ,它的 IFoo.X 。该防爆pression.Property 方法需要声明的财产,而不是一个子类的实际类型。如果你不相信,请尝试:

The property you're trying to access is not IBar.X, it's IFoo.X. The Expression.Property method expects the actual type that declares the property, not a subtype. If you're not convinced, try that :

var prop = typeof(IBar).GetProperty("X");

,则返回null(只是因为伊巴尔是一个接口,它会工作的一类)

It returns null (only because IBar is an interface ; it would work for a class)

我想使它工作的最简单的方法是创建一个辅助的方法来解决实际的属性,通过走了类型层次递归:

I think the easiest way to make it work is to create a helper method to resolve the actual property, by walking up the type hierarchy recursively :

private PropertyInfo GetProperty(Type type, string propertyName)
{
    PropertyInfo prop = type.GetProperty(propertyName);
    if (prop == null)
    {
        var baseTypesAndInterfaces = new List<Type>();
        if (type.BaseType != null) baseTypesAndInterfaces.Add(type.BaseType);
        baseTypesAndInterfaces.AddRange(type.GetInterfaces());
        foreach(Type t in baseTypesAndInterfaces)
        {
            prop = GetProperty(t, propertyName);
            if (prop != null)
                break;
        }
    }
    return prop;
}

您可以重新写你的 PropertyOfProperty 如下:

You can then rewrite your PropertyOfProperty as follows :

private static MemberExpression PropertyOfProperty(Expression expr, string propertyName)
{
    return propertyName
               .Split('.')
               .Aggregate<string, MemberExpression>(
                   expr,
                   (current, property) =>
                       Expression.Property(
                           current,
                           GetProperty(current.Type, property)));
}

这篇关于防爆pression树与财产继承导致参数异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆