【发布时间】:2011-05-17 02:27:23
【问题描述】:
我刚刚在我编写的几个解析器中重构了一段通用代码。 该代码用于自动发现方法实现,并且可以非常方便地扩展现有解析器或使用更多 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 ...)实现, 或者我是否应该在发现过程中使用缓存。 我真的不确定反射调用的效率如何。
【问题讨论】:
-
对不起,我想使用标签的自动完成,但我不知何故发布到早期 ^^ 而且我发现反射不是拼写反射^^
-
您能否解释一下“可能频繁创建和销毁的类”的含义?您的意思是
DynamicCallableMethodTable<TClass, THandle>实例通常是短暂的吗?既然类型对我来说似乎是不可变的,为什么不缓存它的实例呢? -
DynamicCallableMethodTable
也适用于实例方法(因此实例参数将是方法的实例,我将编辑示例 -
我不能使用调试器来处理常见的情况,因为它在很远的服务器中使用,所以我认为我不能真正有效地节省时间,我更希望能进入后面.NET 实现,如果已经有足够的缓存在进行,那么我不想重复缓存逻辑...
-
是的,它叫做 MemberInfo 缓存。更多信息在这里:msdn.microsoft.com/en-us/magazine/cc163759.aspx
标签: c# .net reflection overhead getmethod