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



有什么方法可以做到这一点吗?我试着测试一个对象的属性是否存在,如果存在,我想给它设置一个值

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

我认为每次使用反射都有点慢,因此,如果多次进行初始化,则可以使用表达式树。但每次您的字典都应该具有相同的初始化属性顺序。

可能的代码

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

最新更新