什么是判断方法是否是Policy Injection中的属性的最佳方法?

时间:2008-09-16 15:18:34

标签: c# enterprise-library policy-injection

我有一个应用于类的自定义处理程序(使用entlib 4中的Policy Injection Application Block),我想知道在调用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 个答案:

答案 0 :(得分:4)

您还可以检查IsSpecialName是否为true。这在属性(以及其他事项)中都是正确的

在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_Foo方法发出一个类,该方法看起来就像一个真正的set方法,但实际上并不是只读属性的一个集合。 除非您检查属性CanRead / CanWrite是否也是。

虽然你并不期待故意的规避,但这让我感到很疯狂。 MethodInfo上的一个简单的实用程序/扩展方法,它执行此逻辑并不会太难,包括IsSpecialName几乎肯定会满足您的所有需求。

答案 1 :(得分:0)

您可以检查IsSpecialName属性;财产获取者和制定者都是如此。但是,对于其他特殊方法也是如此,例如运算符重载。

答案 2 :(得分:0)

我不熟悉该应用程序块,但假设MethodBase属性的类型为System.Reflection.MethodBase,您可以查看IsSpecialName属性。

System.Reflection.MethodBase.IsSpecialName on MSDN

答案 3 :(得分:0)

有几个人提到过使用MethodBase类型的“IsSpecialName”属性。虽然对于属性“gets”或“sets”,它将返回true,但对于运算符重载(例如add_EventName或remove_EventName),它也将返回true。因此,您需要检查MethodBase实例的其他属性,以确定它是否为属性访问器。不幸的是,如果您拥有的只是对MethodBase实例的引用(我认为是Unity框架中拦截行为的情况),那么确定它是属性setter还是getter并不是真正的“干净”方法。我发现的最好方法如下:

C#:

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

答案 4 :(得分:0)

有点晚了,但其他人也会读到这个。除了IsSpecialName并检查set_前缀(运算符有op_,事件subscr./remov。有add_,remove_),您可以检查方法是否与任何属性方法匹配,如下所示:

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