如何解决C#-一种更快的方法来获取设置的公共静态字段,而不是使用Reflection.SetValue / GetValue
我有一个需要在运行时更改公共静态字段的场景。我知道我可以通过以下反射来完成此操作,以设置所需的公共静态字段,但这确实很慢。
string typeName = "ABC";
string fieldName = "IsA";
Type.GetType(typeName ).GetField(fieldName ).SetValue(null,value);
var value = Type.GetType(typeName ).GetField(fieldName ).GetValue(null);
我想知道是否有任何更快的访问方式,例如使用Reflection.Emit,Linq.Expression或其他方法。据我所知,目前大多数它们仅支持带有实例的字段。
解决方法
您可以为此使用表达式。您基本上有三个选择:
- 反思。慢点。
- 动态编译表达式。快。
- 键入已编译的表达式。超级快。
对于您来说,使用类型化表达式有点棘手。我想我们不能假设所有静态属性的类型都为string
?第二个选项使您可以轻松地为任何字段类型创建快速设置器。
请注意,在编译表达式时,必须维护已编译委托的缓存。编译步骤非常昂贵!
class Program
{
public class Foo
{
public static string Name;
}
public static void Main()
{
var delegateCache = new Dictionary<(string,string),Delegate>();
var typeName = typeof(Foo).FullName;
var fieldName = "Name";
var key = (typeName,fieldName);
// Caching is crucial!
if (!delegateCache.TryGetValue(key,out var d))
{
d = CreateStaticSetter(typeName,fieldName);
delegateCache.Add(key,d);
}
// For a strongly typed delegate,we would use Invoke() instead.
d.DynamicInvoke("new value");
Console.WriteLine(Foo.Name);
}
private static Delegate CreateStaticSetter(string typeName,string fieldName)
{
var type = Type.GetType(typeName) ?? throw new ArgumentException();
var field = type.GetField(fieldName) ?? throw new ArgumentException();
var valueExp = Expression.Parameter(field.FieldType,"value");
var fieldExp = Expression.Field(null,field);
var assignExp = Expression.Assign(fieldExp,valueExp);
// TODO: Can be further optimized with a strongly typed delegate.
var expr = Expression.Lambda(assignExp,valueExp);
return expr.Compile();
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。