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

时间:2014-12-18 15:08:29

标签: 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;
    }

1 个答案:

答案 0 :(得分:3)

当然可以缓存通过反射获得的字段访问器。我们在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();
}

参考:ObjectModelAdaptor