【发布时间】:2016-12-22 22:18:24
【问题描述】:
我正在尝试为类中的所有字段实现静态反射。 换句话说,我必须使用名称为所有这些字段创建 get 和 set。
我使用Set field value with Expression tree上的答案,得出以下解决方案
public class ExpressionSetterGetter
{
public class SetterGetter<T> where T : class
{
public Delegate getter;
public Action<T, object> setter;
}
public static Dictionary<string, SetterGetter<T>> GetFieldSetterGetterExpressions<T>() where T : class
{
var dic = new Dictionary<string, SetterGetter<T>>();
SetterGetter<T> setterGetter;
var type = typeof(T);
var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
foreach (var fieldInfo in fields)
{
var targetExp = Expression.Parameter(type, "target");
var valueExp = Expression.Parameter(typeof(object), "value");
var fieldExp = Expression.Field(targetExp, fieldInfo);
var assignExp = Expression.Assign(fieldExp, Expression.Convert(valueExp, fieldExp.Type));
var fieldSetter = Expression.Lambda<Action<T, object>>(assignExp, targetExp, valueExp).Compile();
ParameterExpression objParm = Expression.Parameter(type, "obj");
MemberExpression fieldExpr = Expression.Field(objParm, fieldInfo.Name);
var fieldExprConverted = Expression.Convert(fieldExpr, typeof(object));
var fieldGetter = Expression.Lambda(fieldExprConverted, objParm).Compile();
setterGetter = new SetterGetter<T>() { setter = fieldSetter, getter = fieldGetter };
dic.Add(fieldInfo.Name, setterGetter);
}
return dic;
}
}
现在,我有这两个问题。
我使用 type.GetFields(),但 MSDN 说它是一种反射方法。 这意味着编译器在运行时之前不知道类型。 我对吗?如果正确,使用的原因是什么 表达树。据我所知,表达式树转换为 编译时的代码,这意味着几乎没有额外的成本。
-
同样的逻辑。如果我将名称为的列表作为参数 字段必须包装的内容。换句话说,而不是 type.GetFields() 我只是把字段的名称作为参数。
public static Dictionary<string, SetterGetter<T>> GetFieldSetterGetterExpressions<T>(IEnumerable<string> fieldNames)
显然,该列表在编译时是未知的。同样,CLR 将如何反应?
【问题讨论】:
-
CLR 不知道表达式树是什么。那只是一个任何人都可以编写的库。
标签: c# reflection expression clr