ExpressionVisitor не посещает переопределенное свойство производного класса - PullRequest
0 голосов
/ 14 октября 2018

Я пытаюсь использовать ExpressionVisitor, чтобы получить переопределенный член выражения, но он дает мне base .Что мне здесь не хватает?

Следующий пример воспроизводит это поведение:

Простые базовые и производные типы:

class Base
{
    public virtual string Property { get; set; }
}

class Derived : Base
{
    public override string Property { get; set; }
}

Я использую это выражение посетитель:

internal class DemoVisitor : ExpressionVisitor
{
    private MemberInfo _member;

    public static MemberInfo GetMemberInfo(LambdaExpression expression)
    {
        var visitor = new DemoVisitor();
        visitor.Visit(expression);

        return visitor._member;
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        // invalid member here
        //node.Member.DeclaringType.Name.Dump();
        _member = _member ?? node.Member;

        return base.VisitMember(node);
    }
}

Называя это так

void Main()
{
    var derived = new Derived();
    var expression = (Expression<Func<string>>)(() => derived.Property);
    DemoVisitor.GetMemberInfo(expression).DeclaringType.Name.Dump();
}

Это возвращает Base вместо Derived.Что мне нужно сделать, чтобы попасть в переопределенный член?

Мне это нужно, потому что я читаю его атрибуты позже, и в настоящее время он дает мне атрибуты свойства базового класса вместо производного.

1 Ответ

0 голосов
/ 14 октября 2018

Если вы хотите узнать тип класса / структуры вашего члена, вам нужно взглянуть на свойство Expression MemberExpression, которое является выражением для объекта, содержащего член - в вашем случае переменная derived- и получите его тип.

Поэтому ваш посетитель должен вернуть оба (здесь я использовал ValueTuple):

internal class DemoVisitor : ExpressionVisitor
{
    private Type type;
    private MemberInfo _member;

    public static (Type, MemberInfo) GetMemberInfo(LambdaExpression expression)
    {
        var visitor = new DemoVisitor();
        visitor.Visit(expression);

        return (visitor.type, visitor._member);
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        if (_member == null)
        {
          _member = node.Member;
          type = node.Expression.Type;
        }

        return base.VisitMember(node);
    }
}

Относительно вашего другого вопроса о том, какого члена посещают: все использованные участники вваше выражение посещено, то есть все методы, свойства и поля, тогда как node.Member возвращает либо MethodInfo, PropertyInfo, либо FieldInfo объект, который все происходит от MemberInfo.

...