我认为每次使用反射有点慢,所以,如果你多次进行初始化,你可以使用表达式树。但是每次你的字典应该有相同的属性顺序来初始化。
可能的代码
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);