Переписать ExpressionTree — MakeMemberAccess() для свойств навигации

Неясно связано с предыдущим вопросом< /эм>

Примечание. Я использую производную версию посетителя ExpressionTree, как описано здесь

В моем методе VisitMemberAccess я в настоящее время создаю MemberExpressions, используя что-то вроде:

// `mapping` is a class used to map EntityA's members to EntityB's members
return Expression.MakeMemberAccess(Visit(m.Expression), mapping.TargetMemberInfo);

По большей части это работает.

Учитывая некоторые тестовые классы...

public class EntityA
{
    public long Id { get; set; }
    public string Name { get; set; }
}

public class EntityB
{
    public long MyId {get; set; }
    public string MyName { get; set; }
}

Код правильно сопоставит (EntityA x) => x.Id с (EntityB x) => x.MyId, что прекрасно и прекрасно работает. Моя проблема возникает, когда вы вводите свойства навигации:

public class EntityB
{
    public long MyId {get; set; }
    public EntityBDetails NavigationProperty { get; set; }
}    

public class EntityBDetails
{
    public string MyName { get; set; }
}

Учитывая приведенный выше тривиальный случай, я бы хотел, чтобы (EntityA x) x => x.Name отображалось на (EntityB x) x => x.NavigationProperty.Name. И в этом проблема, я понятия не имею, что предоставить MakeMemberAccess, чтобы эта работа работала... Я могу сравнить mapping.TargetMemberInfo.DeclaringType == mapping.TargetMemberInfo.ReflectedType, чтобы определить, задействовано ли свойство навигации, но как мне создать необходимое MemberExpression?

Заранее спасибо!

Примечание: кодовая база, над которой я работаю, — VB; С# имеет тенденцию получать лучшие/быстрые ответы на SO, поэтому я конвертировал вручную. Дайте мне знать, если я допустил глупую опечатку/и т. д.


person Smudge202    schedule 07.09.2011    source источник
comment
Я только что нашел этот вопрос - ответ Дэви Лэндмана выглядит так, как будто он содержит то, что мне нужно - нужно уйти и учесть его. Будет обновлено.   -  person Smudge202    schedule 07.09.2011


Ответы (1)


Я думаю, это может помочь перевести код C# на английский язык, а затем перевести его в код, создающий выражения:

Выражение x.NavigationProperty.Name на самом деле означает «доступ к свойству NavigationProperty в x, а затем доступ к свойству Name в результате. Теперь код:

ParameterExpression x = …;
var navigationProperty = typeof(EntityB).GetProperty("NavigationProperty");
var name = typeof(EntityBDetails).GetProperty("Name");

var navigationPropertyAccess = Expression.MakeMemberAccess(x, navigationProperty);
var nameAccess = Expression.MakeMemberAccess(navigationPropertyAccess , name);
person svick    schedule 07.09.2011
comment
-1 Я за конструктивную критику и за то, чтобы меня поправляли, но "I think it could help to translate the C# code into English" мне кажется больше похоже на издевательство... возможно, я неправильно прочитал ваше утверждение? Причина, по которой я назвал это свойство навигации, заключается в том, что именно на него ссылается Entity. Framework, который является ORM, который я использую... - person Smudge202; 08.09.2011
comment
Я не имел в виду насмешку. Похоже, вы не поняли, что вам нужно использовать MakeMemberAccess() дважды, поскольку у вас есть два доступа к свойствам в выражении, которое вы хотите создать. Я знаю, что вы знаете, что делает выражение. Но я думаю, что может быть полезно остановиться и подумать, что это на самом деле означает, переведя C# на английский язык. И я не комментировал название, поэтому я не уверен, почему вы упомянули об этом. - person svick; 08.09.2011
comment
Вы правы, я не осознавал, что мне нужно вызывать MakeMemberExpression несколько раз, пока не прочитал ответ на вопрос, ссылку на который я дал в комментариях выше. Думаю, теперь я понимаю контекст вышеупомянутого заявления. Не стесняйтесь вносить незначительные изменения, и я удалю -1. Спасибо за ответ - person Smudge202; 08.09.2011