如何在策略注入中判断一个方法是否为属性的最佳方法?

3

我已经应用了一个自定义处理程序到一个类上(使用entlib 4中的策略注入应用程序块),我想知道当调用Invoke方法时,输入方法是否是一个属性。以下是我的处理程序的样子。

[ConfigurationElementType(typeof(MyCustomHandlerData))]
public class MyCustomHandler : ICallHandler
{
    public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
    {
        if (input.MethodBase.IsPublic && (input.MethodBase.Name.Contains("get_") || input.MethodBase.Name.Contains("set_")))
        {
            Console.WriteLine("MyCustomHandler Invoke called with input of {0}", input.MethodBase.Name);
        }
        return getNext().Invoke(input, getNext);
    }

    public int Order { get; set; }
}

从我的代码示例中可以看出,目前我想到的最好的方法是通过解析方法名。是否有更好的方法来做到这一点?

5个回答

5

你也可以检查IsSpecialName是否为真。在属性中,它将为真(还有其他情况)

在il级别上,方法的暴露如下(以Environment.ExitCode为例):

.method public hidebysig specialname static int32 get_ExitCode() cil managed
.method public hidebysig specialname static void set_ExitCode(int32 'value') cil managed

如果你想要更加高级一些,你可以在提取名称后验证该属性是否存在,但老实说,这并不必要。
if (m.IsSpecialName && (m.Attributes & MethodAttributes.HideBySig) != 0)) 

如果方法以get_或set_开头,即使使用不好的名称(伪造hidebysig足够容易,伪造IsSpecialName则非常棘手),也应该可以正常工作。
但是并没有什么是绝对可靠的。有人可能会发出一个类,其中包含一个看起来像真正的set方法,但实际上却不是只读属性的set方法。 除非您还检查属性CanRead / CanWrite。
对于您来说,这似乎是疯狂的,因为您并不希望有意规避。 MethodInfo上的一个简单的实用程序/扩展方法可以执行此逻辑,并且包括IsSpecialName几乎肯定可以满足您的所有需求。

注意:如果条件也适用于添加或删除事件处理程序的方法。 - Mr.Yeah

1
有几位提到了使用MethodBase类型的"IsSpecialName"属性。虽然它确实会对“get”或“set”属性返回true,但对于操作符重载(如add_EventName或remove_EventName)也会返回true。因此,您需要检查MethodBase实例的其他属性来确定它是否是属性访问器。不幸的是,如果您只有对MethodBase实例的引用(我认为在Unity框架中拦截行为时就是这种情况),那么没有真正“干净”的方法来确定它是属性设置器还是获取器。我发现最好的方法如下:
bool IsPropertySetter(MethodBase methodBase){
     return methodBase.IsSpecialName && methodBase.Name.StartsWith("set_");
}

bool IsPropertyGetter(MethodBase methodBase){
     return methodBase.IsSpecialName && methodBase.Name.StartsWith("get_");
}

VB:

 Private Function IsPropertySetter(methodBase As MethodBase) As Boolean

      Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("set_")

 End Function

 Private Function IsPropertyGetter(methodBase As MethodBase) As Boolean

      Return methodBase.IsSpecialName AndAlso methodBase.Name.StartsWith("get_")

 End Function

0

虽然有点晚了,但其他人也会看到这篇文章。除了使用IsSpecialName和检查set_前缀(运算符使用op_,事件订阅/移除使用add_,remove_),您还可以像这样检查方法是否与任何属性方法匹配:

    bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p => 
        p.GetGetMethod().GetHashCode() == method.GetHashCode() 
        || p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;

0
你可以检查IsSpecialName属性;对于属性的getter和setter,它将为true。但是,对于其他特殊方法(如运算符重载),它也将为true。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接