使用表达式得到一个POCO对象的属性的名称和值(Get Name and Value of a pr

2019-10-22 03:23发布

我正在寻找一种方式来获得的名称和proptery的值在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(...) ]。 的问题是,我发现了在空REF误差getPropertyValue(Expression<Func<T, object>> expression)时,它调用var ce = (ConstantExpression)me.Expression;

因此,没有人对如何得到这个工作的想法?

感谢您抽出宝贵时间来看看这个。 我真的很感激,并希望我的问题也是对他人有所帮助,因为我认为这可能是相当有用,如果我能得到这个工作。

编辑 :我做了变化中的注释下面提到并仍然得到错误“无法投型‘System.Linq.Expressions.TypedParameterExpression’的对象键入“System.Linq.Expressions.ConstantExpression”当我跑我的单元测试。

Answer 1:

我研究出了解决办法(不幸的是,评论是没有帮助)。 下面是工作的代码:

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();
    }


文章来源: Get Name and Value of a property of a POCO object using an expression