Ответ 1
Да, вы ищете метод PropertyInfo.SetValue, например.
var propInfo = info.GetType().GetProperty(propertyName);
if (propInfo != null)
{
propInfo.SetValue(info, value, null);
}
Есть ли способ сделать это? Я пытаюсь проверить, существует ли свойство объекта, и если да, то я хочу установить для него значение. (Может быть, полная идея плоха, если это правда - почему?)
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);
}
Я думаю, что использование отражения каждый раз немного медленное, поэтому, если вы делаете эту инициализацию более одного раза, вы можете использовать Дерево выражений. Но каждый раз, когда ваш словарь должен иметь одинаковый порядок свойств для 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);