gpt4 book ai didi

c# - GetMethods 中反射的开销是多少

转载 作者:行者123 更新时间:2023-11-30 18:43:34 26 4
gpt4 key购买 nike

我只是在我编写的几个解析器中重构了一段通用代码。该代码用于自动发现方法实现,它非常方便扩展现有解析器或使用更多 DRY 代码(尤其是我一个人在做这个项目):

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class CallableAttribute : Attribute
{
public CallableAttribute()
: this(true)
{
// intentionally blank
}

private CallableAttribute(bool isCallable)
{
Callable = isCallable;
}

public bool Callable { get; private set; }
}

public class DynamicCallableMethodTable<TClass, THandle>
where THandle : class
{
private readonly IDictionary<string, THandle> _table = new Dictionary<string, THandle>();

public DynamicCallableMethodTable(TClass instance, Func<string, string> nameMangler,
BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance)
{
var attributeType = typeof(CallableAttribute);
var classType = typeof(TClass);

var callableMethods = from methodInfo in classType.GetMethods(bindingFlags)
from CallableAttribute a in methodInfo.GetCustomAttributes(attributeType, false)
where a.Callable
select methodInfo;

foreach (var method in callableMethods)
_table[nameMangler(method.Name)] = method.CastToDelegate<THandle>(instance);
}

public bool TryGetMethod(string key, out THandle handle)
{
return _table.TryGetValue(key, out handle);
}
}

public static class MethodEx
{
public static TDelegate CastToDelegate<TDelegate>(this MethodInfo method, object receiver)
where TDelegate : class
{
return Delegate.CreateDelegate(typeof(TDelegate), receiver, method, true) as TDelegate;
}
}

现在我想在一个可能被频繁创建和销毁的类中使用这段代码:

class ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived
{
private DynamicCallableMethodTable<string, TSomeDelegate> _table = ...
public ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived()
{
_table = new DynamicCallableMethodTable<string, TSomeDelegate>(this, ...);
}
}

所以我在 GetMethods 的开销上徘徊,如果 .NET(4.0 可以使用...)实现中已经有一些缓存,或者我是否应该在发现过程中使用缓存。我真的不确定反射调用的效率如何。

最佳答案

基于@Sergey的以下想法

Yes, it's called MemberInfo cache. More on it here: msdn.microsoft.com/en-us/magazine/cc163759.aspx – Sergey

我将静态代码提取到一个静态类中,它基于通用静态类字段将有自己的槽的假设(即使它不使用通用参数?)。虽然我不确定我是否不应该直接存储 MethodInfo。从长远来看,RuntimeMethodHandle 似乎可以节省空间。

static class ReflectionMethodCache<TClass>
{
/// <summary>
/// this field gets a different slot for every usage of this generic static class
/// http://stackoverflow.com/questions/2685046/uses-for-static-generic-classes
/// </summary>
private static readonly ConcurrentDictionary<BindingFlags, IList<RuntimeMethodHandle>> MethodHandles;

static ReflectionMethodCache()
{
MethodHandles = new ConcurrentDictionary<BindingFlags, IList<RuntimeMethodHandle>>(2, 5);
}

public static IEnumerable<RuntimeMethodHandle> GetCallableMethods(BindingFlags bindingFlags)
{
return MethodHandles.GetOrAdd(bindingFlags, RuntimeMethodHandles);
}

public static List<RuntimeMethodHandle> RuntimeMethodHandles(BindingFlags bindingFlags)
{
return (from methodInfo in typeof (TClass).GetMethods(bindingFlags)
from CallableAttribute a in
methodInfo.GetCustomAttributes(typeof (CallableAttribute), false)
where a.Callable
select methodInfo.MethodHandle).ToList();
}
}

public class DynamicCallableMethodTable<TClass, THandle>
where THandle : class
{
private readonly IDictionary<string, THandle> _table = new Dictionary<string, THandle>();

public DynamicCallableMethodTable(TClass instance, Func<string, string> nameMangler,
BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance)
{
var callableMethods = ReflectionMethodCache<TClass>.GetCallableMethods(bindingFlags);

foreach (MethodInfo methodInfo in callableMethods.Select(MethodBase.GetMethodFromHandle))
{
_table[nameMangler(methodInfo.Name)] = methodInfo.CastToDelegate<THandle>(instance);
}
}

public bool TryGetMethod(string key, out THandle handle)
{
return _table.TryGetValue(key, out handle);
}
}

public static class MethodEx
{
public static TDelegate CastToDelegate<TDelegate>(this MethodInfo method, object receiver)
where TDelegate : class
{
return Delegate.CreateDelegate(typeof(TDelegate), receiver, method, true) as TDelegate;
}
}

关于c# - GetMethods 中反射的开销是多少,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4300948/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com