2014-11-26 8 views
2

Мне нужна помощь. У меня есть два класса: сущность и модель. Их код ниже.Свойство MemberExpression не определено

public class TestEntityForSerialize 
{ 
    public String FIO { get; set; } 
    public DateTime Birthday { get; set; } 
    public String Name { get; set; } 
} 

[DataContract] 
public class TestModelForSerialize 
{ 
    [DataMember] 
    public String FIO { get; set; } 
    [DataMember] 
    public DateTime Birthday { get; set; } 
    [DataMember(Name = "Name")] 
    public String BigName { get; set; } 
    public Int32 Age { get; set; } 
} 

Основная задача состоит в том, чтобы программно конвертировать любые Func<TestModelForSerialize, Boolean> в Func <TestEntityForSerialize, Boolean>. Мое решение - использовать деревья выражений. Я использую ExpressionVisitor для итерации узлов дерева выражений модели и для создания нового параметра Expression with Entity в качестве параметра. Общие параметры этих Func устанавливаются в классе, поддерживая функциональность.

Я преуспел в преобразовании ParameterExpression, переопределив метод VisitParameter, но я застрял с переопределением метода VisitMember для потомка ExpressionVisitor. на самом деле у меня есть код: VisitMember переопределение:

protected override Expression VisitMember(MemberExpression node) 
    {    
     Expression e = base.VisitMember(node); 
     MemberExpression me = e as MemberExpression; 
     if (me != null) 
     { 
      String modelPropertyName = ((PropertyInfo)me.Member).Name; 
      ParameterExpression pe = node.Expression as ParameterExpression; 
      TModel m = Activator.CreateInstance<TModel>(); 
      PropertyInfo memberPI = GetEntityProperty(m, modelPropertyName); 
      MemberExpression meToReturn = Expression.Property(Expression.Parameter(typeof(TEntity)), memberPI); 

      return meToReturn; 
     } 
     else 
     { 
      return base.VisitMember(node); 
     } 
    } 

VisitParameter переопределение:

protected override Expression VisitParameter(ParameterExpression node) 
    { 
     ParameterExpression pe = base.VisitParameter(node) as ParameterExpression; 
     if (pe.Type == typeof(TModel)) 
     { 
      ParameterExpression ex = Expression.Parameter(typeof(TEntity), pe.Name); 
      return ex; 
     } 
     else 
     { 
      return pe; 
     } 
    } 

GetEntityProperty является метод отображения свойство класса TModel свойству класса TEntity. Он использует DataContract и DataMember для сопоставления.

protected PropertyInfo GetEntityProperty(TModel model, String propertyName) 
    { 
     PropertyInfo property = model.GetType().GetProperty(propertyName); 
     if (property != null) 
     { 
      Attribute attr = property.GetCustomAttribute(typeof(DataMemberAttribute)); 
      if (attr != null) 
      { 
       String entityPropertyName = (((DataMemberAttribute)attr).Name != null ? ((DataMemberAttribute)attr).Name : propertyName); 
       return typeof(TEntity).GetProperty(entityPropertyName); 
      } 
      else 
      { 
       throw new DataMemberAttributeNotFoundException(); 
      } 
     } 
     else 
     { 
      throw new MissingMemberException(); 
     } 
    } 

The TestMethod является

[TestMethod] 
    public void TestVisitMemberShouldReplaceModelWithEntity() 
    { 
     ParameterExpression p = Expression.Parameter(typeof(TestModelForSerialize)); 
     Type tm = typeof(TestModelForSerialize); 
     PropertyInfo birthdayProp = tm.GetProperty("FIO"); 
     Assert.IsNotNull(birthdayProp); 
     MemberExpression me = Expression.Property(p, birthdayProp); 
     VisitorForTests vft = new VisitorForTests(); 
     MemberExpression meResult = vft.VisitMemberForTest(me) as MemberExpression; 
     Assert.IsInstanceOfType(meResult.Member, typeof(PropertyInfo)); 
    } 

VisitorForTests класс для вызова защищенного метода в классе, я пытаюсь заниматься. Это метод:

public Expression VisitMemberForTest(MemberExpression node) 
    { 
     return this.VisitMember(node); 
    } 

Когда я пытаюсь вызвать метод VisitMember, он давит на первой линии («Выражение е = base.VisitMember (узел);»), метание ArgumentException с сообщением: Property «FIO» является не определен в классе «TestEntityForSerialize». Единственное, что я мог заметить - VisitMember пытается запустить метод VisitParameter, а после получения его результата - раздавит.

Любая помощь очень ценится.

+0

Не могли бы вы включить полный код, демонстрирующий проблему? В частности: как реализуется «GetEntityProperty()»? Откуда берутся общие параметры? – svick

+0

Спасибо за ответ. GetEntityProperty() - метод, вычисляющий отображение свойства Entity в свойство Model. Он был протестирован и работал правильно. Общие параметры, заданные в классе, который содержит метод. Я постараюсь продлить эту должность. –

ответ

1

Gotcha! Как говорится в российской пословице: «Спасение человека - это дело рук этого человека». Проблема была в том, что я пытался использовать Expression с неправильными параметрами. Он должен быть снабжен собственностью TEntity, и я бы поставил его с помощью TModel. Так что просто измените метод VisitMember и Qawabanga!

protected override Expression VisitMember(MemberExpression node) 
    {    
     //Expression e = base.VisitMember(node); - I've commented this line 
     MemberExpression me = node as MemberExpression; 
     if (me != null) 
     { 
      String modelPropertyName = ((PropertyInfo)me.Member).Name; 
      ParameterExpression pe = node.Expression as ParameterExpression; 
      TModel m = Activator.CreateInstance<TModel>(); 
      PropertyInfo memberPI = GetEntityProperty(m, modelPropertyName); 
      MemberExpression meToReturn = Expression.Property(Expression.Parameter(typeof(TEntity)), memberPI.Name); 

      return base.VisitMember(meToReturn); //and changed this line 
     } 
     else 
     { 
      return base.VisitMember(node); 
     } 
    } 

И это работает!

Смежные вопросы