2012-08-06 7 views
11

これを実行する方法はありますか?私は、オブジェクトのプロパティが存在するかどうかをテストしようとします。存在する場合は、値を設定したいと思います。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? 
    } 
} 
+0

あなたがこのの多くを行っている場合は、あなたがそのような[FastMember]として最適化ツールを使用することもできます(http://nuget.org/packages/FastMember) –

答えて

28

はい、あなたは、例えばPropertyInfo.SetValue方法を探して - (?なぜ真の場合はたぶん完全なアイデアは、悪いです)

あなたは財産上の SetValueメソッドを呼び出す必要があり
var propInfo = info.GetType().GetProperty(propertyName); 
if (propInfo != null) 
{ 
    propInfo.SetValue(info, value, null); 
} 
3

:私はあなたが何度もその初期よりをすれば反射を利用するたびに、少し遅いです、そう思う

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

を式ツリーを使用できます。しかし、あなたの辞書は、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); 
関連する問題