繁体   English   中英

C#通过变量名获取和设置属性

[英]C# get and set property by variable name

有没有办法做到这一点? 我尝试测试对象的属性是否存在,如果存在,我想为它设置一个值。 (也许完整的想法很糟糕,如果是真的 - 为什么?)

class Info
{
    public string X1{ set; get; }
    public string X2{ set; get; }
    public string X3{ set; get; }
}

Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("X1","blah1");
values.Add("X2","blah2");
values.Add("NotThere","blah3");

Info info = new Info();

foreach (var item in values)
{
  string propertyName = item.Key;
  string value = item.Value;
  if (info.GetType().GetProperty(propertyName) != null)  //this probably works
  {
        info.propertyName = value; //this doesn't, how to set it?
  }
}

是的,您正在寻找PropertyInfo.SetValue方法,例如

var propInfo = info.GetType().GetProperty(propertyName);
if (propInfo != null)
{
    propInfo.SetValue(info, value, null);
}
var propertyInfo = info.GetType().GetProperty(propertyName);
if (propertyInfo != null)  //this probably works. Yes it is
  {
        propertyInfo.SetValue(info, value, null);
  }

您需要在属性上调用SetValue方法:

var property = info.GetType().GetProperty(propertyName);
if (property != null)
{
    property.SetValue(info, value, null); 
}

我认为每次使用反射都有点慢,所以,如果你不止一次进行初始化,你可以使用表达式树。 但每次你的字典应该具有相同的init属性顺序。

可能的代码

class Info
{
    public string X1 { set; get; }
    public string X2 { set; get; }
    public int X3 { set; get; }
    private Action<Info, List<object>> initAction;

    public void Init(Dictionary<string, object> initDict)
    {
        //on first usage we deal with reflection and build expression tree to init properties
        if (initAction==null)
        {
            ParameterExpression targetInstanceExpression = Expression.Parameter(this.GetType());
            ParameterExpression valuesExpression = Expression.Parameter(typeof(List<object>));
            ParameterExpression value = Expression.Variable(typeof(object));
            ParameterExpression enumerator = Expression.Variable(typeof(IEnumerator));

            var expList = new List<Expression>();
            expList.Add(Expression.Assign(enumerator, Expression.TypeAs(Expression.Call(valuesExpression, "GetEnumerator", null),typeof(IEnumerator))));
            foreach (var initRecord in initDict)
            {
                Expression moveNextExp = Expression.Call(enumerator, "MoveNext", null);
                expList.Add(moveNextExp);
                Type type = initRecord.Value.GetType();
                expList.Add(Expression.Assign(value, Expression.PropertyOrField(enumerator, "Current")));
                Expression assignExp = GetPropAssigner(initRecord.Key, type, targetInstanceExpression, value);
                expList.Add(assignExp);
            }
            Expression block = Expression.Block
            (
                 new[] { value, enumerator },
                 expList
            );
            //compile epression tree and get init action 
            initAction = Expression.Lambda<Action<Info, List<object>>>(block, targetInstanceExpression, valuesExpression).Compile();
        }
        initAction(this, initDict.Values.ToList());
    }
    //little method to create property assigner
    public static Expression GetPropAssigner(string propName, Type type,
         ParameterExpression targetInstanceExp, ParameterExpression valueExp)
    {
        MemberExpression fieldExp = Expression.PropertyOrField(targetInstanceExp, propName);
        BinaryExpression assignExp = Expression.Assign(fieldExp, type.IsValueType ? Expression.Unbox(valueExp, type) : Expression.TypeAs(valueExp, type));
        return assignExp;
    }
}

用法:

var values = new Dictionary<string, object>();
            values.Add("X1", "blah1");
            values.Add("X2", "blah2");
            values.Add("X3", 8);


Info info = new Info();
info.Init(values);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM