有没有办法做到这一点?我尝试测试对象的属性是否存在,如果存在,我想为它设置一个值。 (也许完整的想法很糟糕,如果是真的 - 为什么?)
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 :(得分:29)
是的,您正在寻找PropertyInfo.SetValue方法,例如
var propInfo = info.GetType().GetProperty(propertyName);
if (propInfo != null)
{
propInfo.SetValue(info, value, null);
}
答案 1 :(得分:7)
var propertyInfo = info.GetType().GetProperty(propertyName);
if (propertyInfo != null) //this probably works. Yes it is
{
propertyInfo.SetValue(info, value, null);
}
答案 2 :(得分:4)
您需要在属性上调用SetValue
方法:
var property = info.GetType().GetProperty(propertyName);
if (property != null)
{
property.SetValue(info, value, null);
}
答案 3 :(得分: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);