C#FieldInfo反射替代方案

时间:2016-07-22 14:11:36

标签: c# reflection fieldinfo

我目前在我的程序中使用了FieldInfo.GetValueFieldInfo.SetValue,这大大减慢了我的程序。

对于PropertyInfo我使用GetValueGetterGetValueSetter方法,因此我只对给定类型使用一次反射。对于FieldInfo,方法不存在。

FieldInfo的建议方法是什么?

编辑: 我从this useful link回复了CodeCaster's。这是一个很好的搜索方向。

现在只有""我不知道如何使用字段的名称来缓存getter / setter并以通用方式重用它们 - 这基本上就是{{1}正在做

SetValue

1 个答案:

答案 0 :(得分:1)

您可以使用Expression来生成更快的字段访问者。如果您希望它们使用Object而不是字段的具体类型,则必须在表达式中添加强制转换(Convert)。

using System.Linq.Expressions;

class FieldAccessor
{
    private static readonly ParameterExpression fieldParameter = Expression.Parameter(typeof(object));
    private static readonly ParameterExpression ownerParameter = Expression.Parameter(typeof(object));

    public FieldAccessor(Type type, string fieldName)
    {
        var field = type.GetField(fieldName,
            BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
        if (field == null) throw new ArgumentException();

        var fieldExpression = Expression.Field(
            Expression.Convert(ownerParameter, type), field);

        Get = Expression.Lambda<Func<object, object>>(
            Expression.Convert(fieldExpression, typeof(object)),
            ownerParameter).Compile();

        Set = Expression.Lambda<Action<object, object>>(
            Expression.Assign(fieldExpression,
                Expression.Convert(fieldParameter, field.FieldType)), 
            ownerParameter, fieldParameter).Compile();
    }

    public Func<object, object> Get { get; }

    public Action<object, object> Set { get; }
}

用法:

class M
{
    private string s;
}

var accessors = new Dictionary<string, FieldAccessor>();

// expensive - you should do this only once
accessors.Add("s", new FieldAccessor(typeof(M), "s"));

var m = new M();
accessors["s"].Set(m, "Foo");
var value = accessors["s"].Get(m);