Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# GetMethods中反射的开销是多少_C#_.net_Reflection_Overhead_Getmethod - Fatal编程技术网

C# GetMethods中反射的开销是多少

C# GetMethods中反射的开销是多少,c#,.net,reflection,overhead,getmethod,C#,.net,Reflection,Overhead,Getmethod,我刚刚在我编写的几个解析器中重构了一段常见的代码。 该代码用于自动发现方法实现,扩展现有解析器或使用更为枯燥的代码非常方便(尤其是我正在单独处理此项目): [AttributeUsage(AttributeTargets.Method,AllowMultiple=false)] 公共类CallableAttribute:属性 { 公共CallableAttribute() :这是真的 { //故意空白 } 私有CallableAttribute(bool可调用) { 可调用=可调用; } pub

我刚刚在我编写的几个解析器中重构了一段常见的代码。 该代码用于自动发现方法实现,扩展现有解析器或使用更为枯燥的代码非常方便(尤其是我正在单独处理此项目):

[AttributeUsage(AttributeTargets.Method,AllowMultiple=false)]
公共类CallableAttribute:属性
{
公共CallableAttribute()
:这是真的
{
//故意空白
}
私有CallableAttribute(bool可调用)
{
可调用=可调用;
}
public bool可调用{get;private set;}
}
公共类DynamicCallableMethodTable
桑德尔在哪里上课
{
私有只读IDictionary _table=new Dictionary();
公共DynamicCallableMethodTable(TClass实例、Func nameMangler、,
BindingFlags BindingFlags=BindingFlags.NonPublic | BindingFlags.Instance)
{
var attributeType=typeof(CallableAttribute);
var classType=typeof(TClass);
var callableMethods=来自classType.GetMethods(bindingFlags)中的methodInfo
来自methodInfo.GetCustomAttributes中的CallableAttribute a(attributeType,false)
a.哪里可以打电话
选择methodInfo;
foreach(callableMethods中的var方法)
_表[nameMangler(method.Name)]=method.CastToDelegate(实例);
}
public bool TryGetMethod(字符串键,out THandle句柄)
{
返回_table.TryGetValue(键,输出句柄);
}
}
公共静态类MethodEx
{
公共静态TDelegate CastToDelegate(此MethodInfo方法,对象接收器)
TDelegate:类在哪里
{
返回Delegate.CreateDelegate(typeof(TDelegate)、receiver、method、true)作为TDelegate;
}
}
现在,我想在一个可能频繁创建和销毁的类中使用此代码:

class ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived
{
    private DynamicCallableMethodTable<string, TSomeDelegate> _table = ...
    public ClassWhichUsesDiscoveryOnInstanceMethodAndIsShortLived()
    {
        _table = new DynamicCallableMethodTable<string, TSomeDelegate>(this, ...);
    }
}
发现InstanceMethod且短激活的类
{
私有DynamicCallableMethodTable _表=。。。
发现InstanceMethod且被短激活的公共类()
{
_表=新的DynamicCallableMethodTable(此,…);
}
}
因此,我在讨论GetMethods的开销,如果.NET(可以使用4.0…)实现中已经有一些缓存, 或者我是否应该在发现过程中使用缓存。
我真的不确定反射调用的效率。

基于@Sergey的以下想法


是的,它叫MemberInfo缓存。更多信息请访问: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;
    }
}
静态类ReflectionMethodCache
{
/// 
///对于此泛型静态类的每次使用,此字段都会获得不同的插槽
/// http://stackoverflow.com/questions/2685046/uses-for-static-generic-classes
/// 
私有静态只读ConcurrentDictionary方法句柄;
静态反射方法缓存()
{
MethodHandles=新的ConcurrentDictionary(2,5);
}
公共静态IEnumerable GetCallableMethods(BindingFlags BindingFlags)
{
return MethodHandles.GetOrAdd(bindingFlags,RuntimeMethodHandles);
}
公共静态列表RuntimeMethodHandles(BindingFlags BindingFlags)
{
返回(来自typeof(TClass).GetMethods(bindingFlags)中的methodInfo)
从中的CallableAttribute a
methodInfo.GetCustomAttributes(typeof(CallableAttribute),false)
a.哪里可以打电话
选择methodInfo.MethodHandle).ToList();
}
}
公共类DynamicCallableMethodTable
桑德尔在哪里上课
{
私有只读IDictionary _table=new Dictionary();
公共DynamicCallableMethodTable(TClass实例、Func nameMangler、,
BindingFlags BindingFlags=BindingFlags.NonPublic | BindingFlags.Instance)
{
var callableMethods=ReflectionMethodCache.GetCallableMethods(bindingFlags);
foreach(callableMethods.Select(MethodBase.GetMethodFromHandle)中的MethodInfo方法信息)
{
_表[nameMangler(methodInfo.Name)]=methodInfo.CastToDelegate(实例);
}
}
public bool TryGetMethod(字符串键,out THandle句柄)
{
返回_table.TryGetValue(键,输出句柄);
}
}
公共静态类MethodEx
{
公共静态TDelegate CastToDelegate(此MethodInfo方法,对象接收器)
TDelegate:类在哪里
{
返回Delegate.CreateDelegate(typeof(TDelegate)、receiver、method、true)作为TDelegate;
}
}

对不起,我想使用标记的自动完成功能,但不知怎的,我发布到了early^^^而且我发现反射不是拼写反射^^^^您能澄清一下“可能频繁创建和销毁的类”是什么意思吗?您的意思是
DynamicCallableMethodTable
实例通常是短期的吗?既然类型在我看来是不可变的,为什么不缓存它的实例呢?DynamicCallableMethodTable也适用于实例方法(因此实例参数将是该方法的一个实例,我将编辑一个示例我不能使用调试器处理频繁的情况,因为调试器在很远的服务器上使用,所以我认为我不能真正高效地利用时间,我更希望进入.NET实现的内部,如果已经有足够的缓存,那么我就不需要了想要重复缓存逻辑…是的,它被称为MemberInfo缓存。这里有更多关于它的信息:很好,因此可以阅读代码中的链接并链接它,多么神奇!:)链接用于静态泛型类?
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;
    }
}