2012-08-06 10 views
11

Gibt es eine Möglichkeit, dies zu tun? Ich versuche zu testen, ob eine Eigenschaft eines Objekts existiert, und wenn es so ist, möchte ich einen Wert darauf setzen. (Vielleicht ist die komplette Idee ist schlecht, wenn sie wahr ist - warum)C# Eigenschaft durch Variablennamen abrufen und festlegen

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

Wenn Sie viele dies tun, können Sie ein optimiertes Werkzeug wie [FastMember] verwenden möchten (http://nuget.org/Pakete/FastMember) –

Antwort

28

Ja, Ihre Suche nach dem PropertyInfo.SetValue Verfahren z.B.

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

Sie benötigen die SetValue Methode auf dem Grundstück aufzurufen:

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

ich mithilfe von Reflektion denke jedes Mal ein bisschen langsam ist, so, wenn Sie diese Initialisierung mehr tun, als wenn Sie kann den Ausdrucksbaum verwenden. Aber jedes Mal sollte Ihr Wörterbuch dieselbe Reihenfolge von Eigenschaften wie init haben.

Mögliche Code

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

Verbrauch:

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