使用表达式获取POCO对象的属性的名称和值 [英] Get Name and Value of a property of a POCO object using an expression

查看:432
本文介绍了使用表达式获取POCO对象的属性的名称和值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种方式来获取POCO对象中的发音的名称和价值。我尝试了许多解决方案,但似乎无法让他们工作。我真的很喜欢这个旧的解决方案,但它会导致空参考错误。



这是我想要做的事情:

  public class POCO 
{
public int ID {get;组; }
public string Name {get;组; }
public string Surname {get;组; }
public string描述{get;组; }
}

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

public abstract class Validator< T>其中T:class
{
public T Entity {get;组; }

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)
{
返回新的POCOValidationResult()
{
错误= string.Format({0}值太长,必须小于或等于{1},propertyName,maxLength.ToString())
};
}

返回新的POCOValidationResult(){IsValid = true};
}

内部字符串getPropertyName(表达式< Func< T,对象>>表达式)
{
var memberExpersion =(MemberExpression)expression.Body;

return memberExpersion.Member.Name;
}
内部字符串getPropertyValue< R>(表达式< Func< T,R>>表达式)
{
//努力使此工作

var me =(MemberExpression)expression.Body; //(MemberExpression)((MemberExpression)expression.Body).Expression;
var ce =(ConstantExpression)me.Expression; //错误在这里
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;

返回新的POCOValidationResult(){IsValid = true};
}
}

public class WorkerBee
{
public void ImDoingWorkReally()
{
var pocoVallidation = new POCOValidator )
{
Entity = new POCO()
{
ID = 1,
Name =James,
Surname =Dean,
描述=我不是007!
}
};

var vallidationResult = pocoVallidation.Validate();

if(!vallidationResult.IsValid)
{
return;
}

//继续做工作...
}
}

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

workerBee.ImDoingWorkReally();
}
}

所以你可以看到,我试图获取属性的名称和值[通过使用表达式(p => p.Surname)作为参数在方法 ValidateStringPropertyToLengthOf(... )]。问题是,当调用 var时,我在 getPropertyValue(Expression< Func< T,object>> expression)中得到一个空参考错误ce =(ConstantExpression)me.Expression;



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

$ b感谢你花时间研究一下这个。我真的很感激,希望我的问题也对他人有帮助,因为我认为如果我能让这个工作起来,这可能会比较有用。



编辑:我已经在注释中进行了如下所述的更改,并且仍然收到错误无法将类型为System.Linq.Expressions.TypedParameterExpression的对象类型为System.Linq.Expressions.ConstantExpression,当我运行我的单元测试。

解决方案

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

  public class POCO 
{
public int ID {get;组; }
public string Name {get;组; }
public string Surname {get;组; }
public string描述{get;组; }
}

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

public abstract class Validator< T>其中T:class
{
public T Entity {get;组; }

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)
{
返回新的POCOValidationResult()
{
错误= string.Format({0}值太长,必须小于或等于{1},propertyName,maxLength.ToString())
};
}

返回新的POCOValidationResult(){IsValid = true};
}

内部字符串getPropertyName(表达式< Func< T,对象>>表达式)
{
var memberExpersion =(MemberExpression)expression.Body;

return memberExpersion.Member.Name;
}
内部字符串getPropertyValue(表达式< Func< T,对象>>表达式)
{
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;

返回新的POCOValidationResult(){IsValid = true};
}
}

public class WorkerBee
{
public void ImDoingWorkReally()
{
var pocoVallidation = new POCOValidator )
{
Entity = new POCO()
{
ID = 1,
Name =James,
Surname =Dean,
描述=我不是007!
}
};

var vallidationResult = pocoVallidation.Validate();

if(!vallidationResult.IsValid)
{
return;
}

//继续做工作...
}
}

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

workerBee.ImDoingWorkReally();
}
}

请注意 getPropertyValue的更改

 内部字符串getPropertyValue(表达式< Func< T,对象>>表达式)
{
var memberExpression = expression.Body as MemberExpression;
var propertyInfo = memberExpression.Member as PropertyInfo;

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


I'm looking for a way to get the name and value of a proptery in a POCO object. I've tried many solutions but can't seem to get them to work. I really liked this older solution but it causes a null ref error.

Here's kind of what I'm trying to do:

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

So as you can see, I'm trying to get the Property's name and value [by using an Expression (p => p.Surname) as a parameter in the method ValidateStringPropertyToLengthOf(...)]. The problem is that I'm getting a null ref error in getPropertyValue(Expression<Func<T, object>> expression) when it calls var ce = (ConstantExpression)me.Expression;

So does anyone have ideas on how to get this to work?

Thanks for taking the time to look into this. I really appreciate it and hope that my question also is helpful for others as I think this can be rather useful if I can get this to work.

EDIT: I've made the change as mentioned below in the comments and still getting the error "Unable to cast object of type 'System.Linq.Expressions.TypedParameterExpression' to type 'System.Linq.Expressions.ConstantExpression" when I run my unit test.

解决方案

I worked out a solution (unfortunately the comments were not helpful). Here's the code that works:

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

Note the change for 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();
    }

这篇关于使用表达式获取POCO对象的属性的名称和值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆