我正在寻找一种方法来获取POCO对象中的一个proptery的名称和价值。我尝试了很多解决方案,但似乎无法让它们发挥作用。我真的很喜欢this旧解决方案,但它会导致空引用错误。
以下是我尝试做的事情:
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;
收到空引用错误
所有人都有关于如何使其发挥作用的想法吗?
感谢您抽出宝贵时间来研究这个问题。我真的很感激,并希望我的问题对其他人也有帮助,因为我认为如果能让这个工作起作用,这可能会非常有用。
编辑:我已在评论中进行了如下所述的更改,但仍然收到错误&#34;无法投放类型&#39; System.Linq.Expressions的对象.TypedParameterExpression&#39;输入&#39; System.Linq.Expressions.ConstantExpression&#34;当我进行单元测试时。
答案 0 :(得分: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();
}