Reputation: 5779
Accessing properties through reflection can lead to significant code reduction for things like ORM, but it usually is fairly slow. When these properties are auto-generated, the backing fields are always in the same position in the struct, and so theoretically, one could access them quickly. In C, you would just cache the offset to the right field in the struct, and call classpointer + fieldoffset
. Is there any way (safe or not) to call Reflection to get that offset and cache it, and once we get it to access the content of the field?
I am thinking of something like this (please forgive my poor knowledge of unsafe syntax):
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;
}
Upvotes: 1
Views: 504
Reputation: 99859
It's certainly possible to cache a field accessor obtained through reflection. We use it extensively in StringTemplate 4 to optimize the rendering pipeline. The following code shows the way we generate an accessor delegate for accessing a field:
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();
}
Reference: ObjectModelAdaptor
Upvotes: 5