是否可以将反射访问器缓存到支持字段以进行优化?

d--*_*--b 1 c# reflection

通过反射访问属性可以显着减少 ORM 之类的代码,但通常速度相当慢。当这些属性自动生成时,支持字段始终位于结构中的相同位置,因此从理论上讲,人们可以快速访问它们。在 C 中,您只需将偏移量缓存到结构中的右侧字段,然后调用classpointer + fieldoffset. 有没有什么方法(安全与否)调用 Reflection 来获取该偏移量并将其缓存,一旦我们获取它就可以访问该字段的内容?

我正在考虑这样的事情(请原谅我对不安全语法的了解不足):

public class Data {
    public double Number { get; set; }
}

public class DataAccessor {
    private static Dictionary<string,int> _offsets;

    public static object Access(Data obj, string field) {
        int offset;
        if (!_offsets.TryGetValue(field, out offset)) {
            offset = typeof(Data).GetBackingFieldOffset(field);
            _offsets[field] = offset;
        }
        object content;
        unsafe {
            fixed(Data* p = obj) {
                content = *(obj + offset);
            }
        }
        return content;
    }
Run Code Online (Sandbox Code Playgroud)

Sam*_*ell 5

当然可以缓存通过反射获得的字段访问器。我们在 StringTemplate 4 中广泛使用它来优化渲染管道。以下代码显示了我们生成用于访问字段的访问器委托的方式:

private static System.Func<object, object> BuildAccessor(FieldInfo field)
{
  ParameterExpression obj = Expression.Parameter(typeof(object), "obj");
  UnaryExpression instance = !field.IsStatic ? Expression.Convert(obj, field.DeclaringType) : null;
  Expression<System.Func<object, object>> expr = Expression.Lambda<System.Func<object, object>>(
    Expression.Convert(
      Expression.Field(instance, field),
      typeof(object)),
    obj);

  return expr.Compile();
}
Run Code Online (Sandbox Code Playgroud)

参考:ObjectModelAdaptor