【问题标题】:C# get and set property by variable nameC#通过变量名获取和设置属性
【发布时间】:2012-08-06 07:49:27
【问题描述】:

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

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?
  }
}

【问题讨论】:

  • 如果您经常这样做,您可能需要使用优化的工具,例如 FastMember

标签: c# string variables properties


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:
    var propertyInfo = info.GetType().GetProperty(propertyName);
    if (propertyInfo != null)  //this probably works. Yes it is
      {
            propertyInfo.SetValue(info, value, null);
      }
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

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

        可能的代码

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-07-22
          • 2012-05-04
          相关资源
          最近更新 更多