2012-08-06 32 views
11

¿Hay alguna manera de hacer esto? Intento probar si existe una propiedad de un objeto y, si lo hace, quiero establecer un valor para él. (Tal vez la idea completa es malo, si es cierto - ¿por qué)C# obtener y establecer la propiedad por nombre de variable

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

Si usted está haciendo un montón de esto, es posible que desee utilizar una herramienta optimizada como [FastMember] (http://nuget.org/packages/FastMember) –

Respuesta

28

Sí, lo que buscas es el método PropertyInfo.SetValue por ejemplo,

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

es necesario invocar el método SetValue en la propiedad:

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

Creo que el uso de la reflexión cada vez es un poco lento, así que, si lo hace que la inicialización más de una vez puede usar Expression Tree. Pero cada vez que su diccionario debe tener el mismo orden de propiedades para iniciar.

código posible

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

Uso:

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