【问题标题】:Identify whether a MethodInfo instance is a property accessor识别 MethodInfo 实例是否是属性访问器
【发布时间】:2011-10-19 09:54:16
【问题描述】:

我正在使用Castle DynamicProxy 编写装饰代理。我需要代理的拦截器只拦截属性写入(而不是读取),因此我正在检查方法的名称:

public void Intercept(IInvocation invocation)
{
    if (invocation.Method.Name.StartsWith("set_")
    {
        // ...
    }

    invocation.Proceed();
}

现在这工作正常,但我不喜欢我的代理对如何实现属性有深入了解的事实:我想用类似的东西替换方法名称检查:

if (invocation.Method.IsPropertySetAccessor)

不幸的是,我的 Google-fu 让我失望了。有什么想法吗?

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    您可以检查是否存在此方法作为设置器的属性(未经测试):

    bool isSetAccessor = invocation.Method.DeclaringType.GetProperties() 
            .Any(prop => prop.GetSetMethod() == invocation.Method)
    

    (灵感来自Marc's answer to a related question。)

    【讨论】:

    • 看起来很无能
    • @thepirat000:好吧,如果GetSetMethod 是 O(1),那么这就是 O(n)。这可能不是最优的(我肯定会支持任何具有同样可读性并产生更好性能的替代答案),但我相信你知道过早优化是万恶之源的说法......
    • 我建议您检查该方法是否具有“get_”前缀(区分大小写)并将其从方法集合中删除(仍然是 O(n) 复杂度 - 这相当便宜)。此外,您可以添加 Dictionary<Type, MethodInfo> 实例来保存已检查的类型,这首先给您 O(n) 的复杂性,然后是 O(1)
    【解决方案2】:

    我知道没有任何巫毒教。您可以,也许,去掉set_,查找具有该名称的属性,并将MethodInfo 实例(invocation.Method) 与属性访问器(GetSetMethod()) 进行比较 - 但是,我不能诚实地说(不检查)你是否会得到相同的 MethodInfo 实例(即使它相同的方法)。

    if(method.IsSpecialName && method.Name.StartsWith("set_"))
    {
        var prop = typeof (Foo).GetProperty(method.Name.Substring(4),
               BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
        var accessor = prop.GetSetMethod();
        bool isSame = accessor == method;
    }
    

    【讨论】:

      【解决方案3】:

      我不确定 invocation.Method 是哪种类型,但如果您可以获得 PropertyInfo,您可以使用 IsSpecialName。不幸的是,这不仅告诉属性是 set_ 还是 _get,还告诉它是否是重载运算符。

      【讨论】:

        【解决方案4】:

        首先,您可以检查MethodInfo 类的MemberType 属性,看看它是否是Property

        现在,您应该尝试猜测它是 get 还是 set。如果您不想分析名称(有人可能将方法命名为“set_Something”),那么您可以检查参数。

        • 如果属性访问器接受一个参数并返回void这是一组
        • 如果属性访问器返回一个值并且不选择参数,这是一个获取

        您可能只对第一次检查感兴趣

        【讨论】:

        • 只是出于好奇而询问。 this[] 运算符呢?我认为它允许一个参数。
        • 属性访问器方法的MemberTypeMemberTypes.Method 而不是MemberTypes.Property。还是谢谢。
        • @dowhilefor: 好点!!!你能在 Reflector/ILDASM 中看到结果并告诉我们吗?我手头没有 Reflector 和带有 this 访问器的程序集,但是 mscorlib.dll 应该充满了它们
        【解决方案5】:

        从您的MethodInfo 对象获取MemberType 属性,它应该说这是一个Property type,因此您应该能够将其转换为PropertyInfo。该对象公开了属性CanWrite,它告诉您这是否是一个setter。

        【讨论】:

        • 嗯,文档似乎暗示 MemberType 对于 MethodInfo 对象将是 MemberTypes.Method
        • 嗯,你说得对,我忽略了这一点,并期望它是为属性创建的 MethodInfo 对象的 MemberTypes.Property,也许我现在不确定了
        • 我刚刚运行了一个测试:属性访问器方法的MemberTypeMemberTypes.Method 而不是MemberTypes.Property,所以这行不通。无论如何,谢谢。
        【解决方案6】:

        我认为您可以尝试使用扩展方法: http://msdn.microsoft.com/en-us/library/bb383977.aspx

        【讨论】:

        • 谢谢,但这就是我当前解决方案的工作方式。我正在寻找一个不需要我的应用程序了解 C# 编译器实现细节的工具。
        • 他可以使用扩展方法将IsPropertySetAccessor 方法添加到MethodInfo 类型,但他遇到的问题是该方法中的内容会比他现在拥有的更好。 “我不喜欢我的代理知道如何实现属性”
        • 这个答案非常无用 - 这个问题似乎更多地指向“什么会在内部确定这个方法”
        猜你喜欢
        • 1970-01-01
        • 2010-11-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-04
        • 1970-01-01
        • 1970-01-01
        • 2011-04-03
        相关资源
        最近更新 更多