Je viens de refactoriser un morceau de code commun dans plusieurs analyseurs que j'ai écrit. Le code est utilisé pour détecter automatiquement les implémentations de méthode et il est assez pratique pour étendre les parseurs existants ou d'utiliser le code plus sec (surtout je travaille sur ce seul projet):Quel est l'overhead de réflexion dans GetMethods
[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;
}
}
Maintenant, je veux utiliser ce code dans une classe qui pourrait être créé et détruit fréquemment:
class ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived
{
private DynamicCallableMethodTable<string, TSomeDelegate> _table = ...
public ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived()
{
_table = new DynamicCallableMethodTable<string, TSomeDelegate>(this, ...);
}
}
donc j'errait sur les frais généraux de GetMethods, s'il y a déjà une mise en cache à l'intérieur du .NET (4.0 peut être utilisé ...) la mise en œuvre , ou si je devrais utiliser la mise en cache pour le processus de découverte. Je ne sais pas vraiment à quel point les appels de réflexion sont efficaces.
désolé je voulais utiliser l'auto-complétion des balises mais je en quelque sorte posté au début ^^ aussi j'ai découvert la réflexion n'est pas orthographié ^^ réflexion – Sebastian
Pouvez-vous préciser ce que vous entendez par « classe qui pourrait être créé et détruit fréquemment "? Voulez-vous dire que les instances de DynamicCallableMethodTable 'sont généralement de courte durée? Puisque le type m'apparaît immuable, pourquoi ne pas en cacher les instances? –
Ani
DynamicCallableMethodTable fonctionne également sur les méthodes d'instance (donc le paramètre instance serait une instance de la méthode, je vais éditer pour un exemple –
Sebastian