2015-03-03 103 views
1

我正在寻找一种方法来获取POCO对象中的属性名称和值。我尝试了很多解决方案,但似乎无法让他们工作。我真的很喜欢this旧的解决方案,但它会导致null ref错误。使用表达式获取POCO对象属性的名称和值

这里是什么样的,我要做的:

public class POCO 
    { 
     public int ID { get; set; } 
     public string Name { get; set; } 
     public string Surname { get; set; } 
     public string Description { get; set; } 
    } 

public class POCOValidationResult 
{ 
    public bool IsValid { get; set; } 
    public string Error { get; set; } 
} 

public abstract class Validator<T> where T : class 
{ 
    public T Entity { get; set; } 

    public abstract POCOValidationResult Validate(); 

    protected POCOValidationResult ValidateStringPropertyToLengthOf(Expression<Func<T, object>> expression, int maxLength) 
    { 
     var propertyName = getPropertyName(expression); 
     var propertyValue = getPropertyValue(expression); 

     if (propertyValue.Length > maxLength) 
     { 
      return new POCOValidationResult() 
      { 
       Error = string.Format("{0} value is too long. Must be less or equal to {1}", propertyName, maxLength.ToString()) 
      }; 
     } 

     return new POCOValidationResult() { IsValid = true }; 
    } 

    internal string getPropertyName(Expression<Func<T, object>> expression) 
    { 
     var memberExpersion = (MemberExpression)expression.Body; 

     return memberExpersion.Member.Name; 
    } 
    internal string getPropertyValue<R>(Expression<Func<T, R>> expression) 
    { 
     //struggling to get this to work 

     var me = (MemberExpression)expression.Body; // (MemberExpression)((MemberExpression)expression.Body).Expression; 
     var ce = (ConstantExpression)me.Expression; // Error here! 
     var fieldInfo = ce.Value.GetType().GetField(me.Member.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); 
     var value = fieldInfo.GetValue(ce.Value); 
    } 
} 

public class POCOValidator : Validator<POCO> 
{ 
    public override POCOValidationResult Validate() 
    { 
     var surnameValidationResult = ValidateStringPropertyToLengthOf(p => p.Surname, 10); 

     if (!surnameValidationResult.IsValid) 
      return surnameValidationResult; 

     //var descriptionValidationResult = ValidateStringPropertyToLengthOf(p => p.Description, 100); 

     //if (!descriptionValidationResult.IsValid) 
     // return descriptionValidationResult; 

     //var nameValidationResult = ValidateStringPropertyToLengthOf(p => p.Name, 15); 

     //if (!nameValidationResult.IsValid) 
     // return nameValidationResult; 

     return new POCOValidationResult() { IsValid = true }; 
    } 
} 

public class WorkerBee 
{ 
    public void ImDoingWorkReally() 
    { 
     var pocoVallidation = new POCOValidator() 
     { 
      Entity = new POCO() 
      { 
       ID = 1, 
       Name = "James", 
       Surname = "Dean", 
       Description = "I'm not 007!" 
      } 
     }; 

     var vallidationResult = pocoVallidation.Validate(); 

     if (!vallidationResult.IsValid) 
     { 
      return; 
     } 

     //continue to do work... 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var workerBee = new WorkerBee(); 

     workerBee.ImDoingWorkReally(); 
    } 
} 

因此,大家可以看到,我想要获得属性的名称和值使用表达式(p => p.Surname)作为一个参数方法ValidateStringPropertyToLengthOf(...)]。问题是我在getPropertyValue(Expression<Func<T, object>> expression)时得到一个空指定错误,当它调用var ce = (ConstantExpression)me.Expression;

那么有没有人有如何让这个工作的想法?

感谢您花时间研究此问题。我非常感谢它,并希望我的问题对其他人也有帮助,因为我认为如果我能够实现这个目标,这可能会非常有用。

编辑:我已经作出的评论下面提到并仍然得到错误“无法投型‘System.Linq.Expressions.TypedParameterExpression’的对象键入“System.Linq.Expressions的变化。 ConstantExpression“当我运行我的单元测试。

+3

我敢肯定,这将解释这个问题http://stackoverflow.com/questions/3567857/why-are- some-object-properties-unaryexpression-and-others-memberexpression/3573250#3573250请删除你的问题,如果是这种情况。 – leppie 2015-03-03 07:47:30

+0

这对我来说看起来像是重复的。根据leppie的建议,您应该将方法声明更改为'string getPropertyValue (Expression > expression)',以便传递正确的表达式类型(即带有正文的表达式)。我会花5分钟来自己测试它,但是你并不打算包含[一个最小的,完整的代码示例](http://stackoverflow.com/help/mcve)。 – 2015-03-03 08:08:37

+0

我欣赏帮助,但更改声明并没有帮助,因为我仍然收到相同的错误:“无法投入'System.Linq.Expressions.TypedParameterExpression'类型的对象来键入'System.Linq.Expressions.ConstantExpression'。 “ – MaudDib 2015-03-03 08:32:54

回答

0

我制定了一个解决方案(不幸的是评论没有帮助)。下面是工作代码:

public class POCO 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string Surname { get; set; } 
    public string Description { get; set; } 
} 

public class POCOValidationResult 
{ 
    public bool IsValid { get; set; } 
    public string Error { get; set; } 
} 

public abstract class Validator<T> where T : class 
{ 
    public T Entity { get; set; } 

    public abstract POCOValidationResult Validate(); 

    protected POCOValidationResult ValidateStringPropertyToLengthOf(Expression<Func<T, object>> expression, int maxLength) 
    { 
     var propertyName = getPropertyName(expression); 
     var propertyValue = getPropertyValue(expression); 

     if (propertyValue.Length > maxLength) 
     { 
      return new POCOValidationResult() 
      { 
       Error = string.Format("{0} value is too long. Must be less or equal to {1}", propertyName, maxLength.ToString()) 
      }; 
     } 

     return new POCOValidationResult() { IsValid = true }; 
    } 

    internal string getPropertyName(Expression<Func<T, object>> expression) 
    { 
     var memberExpersion = (MemberExpression)expression.Body; 

     return memberExpersion.Member.Name; 
    } 
    internal string getPropertyValue(Expression<Func<T, object>> expression) 
    { 
     var memberExpression = expression.Body as MemberExpression; 
     var propertyInfo = memberExpression.Member as PropertyInfo; 

     return propertyInfo.GetValue(Entity, null).ToString(); 
    } 
} 

public class POCOValidator : Validator<POCO> 
{ 
    public override POCOValidationResult Validate() 
    { 
     var surnameValidationResult = ValidateStringPropertyToLengthOf(p => p.Surname, 10); 

     if (!surnameValidationResult.IsValid) 
      return surnameValidationResult; 

     var descriptionValidationResult = ValidateStringPropertyToLengthOf(p => p.Description, 100); 

     if (!descriptionValidationResult.IsValid) 
      return descriptionValidationResult; 

     var nameValidationResult = ValidateStringPropertyToLengthOf(p => p.Name, 15); 

     if (!nameValidationResult.IsValid) 
      return nameValidationResult; 

     return new POCOValidationResult() { IsValid = true }; 
    } 
} 

public class WorkerBee 
{ 
    public void ImDoingWorkReally() 
    { 
     var pocoVallidation = new POCOValidator() 
     { 
      Entity = new POCO() 
      { 
       ID = 1, 
       Name = "James", 
       Surname = "Dean", 
       Description = "I'm not 007!" 
      } 
     }; 

     var vallidationResult = pocoVallidation.Validate(); 

     if (!vallidationResult.IsValid) 
     { 
      return; 
     } 

     //continue to do work... 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var workerBee = new WorkerBee(); 

     workerBee.ImDoingWorkReally(); 
    } 
} 

注意事项getPropertyValue变化:

internal string getPropertyValue(Expression<Func<T, object>> expression) 
    { 
     var memberExpression = expression.Body as MemberExpression; 
     var propertyInfo = memberExpression.Member as PropertyInfo; 

     return propertyInfo.GetValue(Entity, null).ToString(); 
    } 
相关问题