对于属性,有 GetGetMethod
和 GetSetMethod
以便我可以:
Getter = (Func<S, T>)Delegate.CreateDelegate(typeof(Func<S, T>),
propertyInfo.GetGetMethod());
和
Setter = (Action<S, T>)Delegate.CreateDelegate(typeof(Action<S, T>),
propertyInfo.GetSetMethod());
但是我该如何处理 FieldInfo
?
我不是在寻找 GetValue
和 SetValue
的委托(delegate)(这意味着我每次都会调用反射)
Getter = s => (T)fieldInfo.GetValue(s);
Setter = (s, t) => (T)fieldInfo.SetValue(s, t);
但是如果这里有一个 CreateDelegate
方法呢? 我是说since assignments return a value ,我可以像对待方法一样对待赋值吗? 如果可以,是否有 MethodInfo
句柄?换句话说,我如何将正确的 MethodInfo
设置和从成员字段获取值传递给 CreateDelegate
方法,以便我得到一个委托(delegate),我用它可以直接读写字段吗?
Getter = (Func<S, T>)Delegate.CreateDelegate(typeof(Func<S, T>), fieldInfo.??);
Setter = (Action<S, T>)Delegate.CreateDelegate(typeof(Action<S, T>), fieldInfo.??);
我可以构建表达式并编译它,但我正在寻找更简单的东西。最后如果问的问题没有答案我不介意走表达式路线,如下图:
var instExp = Expression.Parameter(typeof(S));
var fieldExp = Expression.Field(instExp, fieldInfo);
Getter = Expression.Lambda<Func<S, T>>(fieldExp, instExp).Compile();
if (!fieldInfo.IsInitOnly)
{
var valueExp = Expression.Parameter(typeof(T));
Setter = Expression.Lambda<Action<S, T>>(Expression.Assign(fieldExp, valueExp), instExp, valueExp).Compile();
}
或者我是在寻找不存在的东西(因为我还没有看到类似的东西)?
最佳答案
正如 Peter Ritchie 所建议的,您可以在运行时编译自己的代码。一旦您第一次调用委托(delegate),该方法就会被编译。因此第一次调用会很慢,但任何后续调用都将尽可能快地进入 .NET,而无需非托管指针/联合。除第一次调用外,委托(delegate)比直接使用 FieldInfo 快大约 500 倍。
class DemoProgram
{
class Target
{
private int value;
}
static void Main(string[] args)
{
FieldInfo valueField = typeof(Target).GetFields(BindingFlags.NonPublic| BindingFlags.Instance).First();
var getValue = CreateGetter<Target, int>(valueField);
var setValue = CreateSetter<Target, int>(valueField);
Target target = new Target();
setValue(target, 42);
Console.WriteLine(getValue(target));
}
static Func<S, T> CreateGetter<S, T>(FieldInfo field)
{
string methodName = field.ReflectedType.FullName + ".get_" + field.Name;
DynamicMethod setterMethod = new DynamicMethod(methodName, typeof(T), new Type[1] { typeof(S) }, true);
ILGenerator gen = setterMethod.GetILGenerator();
if (field.IsStatic)
{
gen.Emit(OpCodes.Ldsfld, field);
}
else
{
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldfld, field);
}
gen.Emit(OpCodes.Ret);
return (Func<S, T>)setterMethod.CreateDelegate(typeof(Func<S, T>));
}
static Action<S, T> CreateSetter<S,T>(FieldInfo field)
{
string methodName = field.ReflectedType.FullName+".set_"+field.Name;
DynamicMethod setterMethod = new DynamicMethod(methodName, null, new Type[2]{typeof(S),typeof(T)},true);
ILGenerator gen = setterMethod.GetILGenerator();
if (field.IsStatic)
{
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Stsfld, field);
}
else
{
gen.Emit(OpCodes.Ldarg_0);
gen.Emit(OpCodes.Ldarg_1);
gen.Emit(OpCodes.Stfld, field);
}
gen.Emit(OpCodes.Ret);
return (Action<S, T>)setterMethod.CreateDelegate(typeof(Action<S, T>));
}
}
请记住,结构是按值传递的。这意味着 Action<S, T>
如果它作为第一个参数按值传递,则不能用于更改结构的成员。
关于c# - 有没有办法创建一个委托(delegate)来获取和设置 FieldInfo 的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16073091/