代码之家  ›  专栏  ›  技术社区  ›  Matt Casto

判断一个方法是否是策略注入中的属性的最佳方法是什么?

  •  3
  • Matt Casto  · 技术社区  · 16 年前

    我已经将一个自定义处理程序应用于一个类(使用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 回复  |  直到 16 年前
        1
  •  3
  •   ShuggyCoUk    16 年前

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

    这让我觉得你疯了,尽管你并不指望故意规避。 MethodInfo上执行此逻辑的简单实用程序/扩展方法不会太难,包括IsSpecialName几乎肯定能满足您的所有需求。

        2
  •  0
  •   Fredrik Kalseth    16 年前

    你们中的一些人提到使用MethodBase类型的“IsSpecialName”属性。虽然对于属性“gets”或“sets”,确实会返回true,但对于运算符重载,如add_EventName或remove_EventName,也会返回true。因此,您需要检查MethodBase实例的其他属性,以确定它是否是属性访问器。不幸的是,如果你只有对MethodBase实例的引用(我认为Unity框架中的拦截行为就是这种情况),那么就没有真正的“干净”方法来确定它是属性设置器还是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
    
        3
  •  0
  •   Nathan Baulch    16 年前

    您可以检查IsSpecialName属性;对于属性getter和setter来说也是如此。然而,对于其他特殊方法也是如此,比如运算符重载。

        4
  •  0
  •   Paul Easter    11 年前

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

    System.Reflection.MethodBase.IsSpecialName on MSDN

        5
  •  0
  •   Tomaz Stih    8 年前

    虽然有点晚了,但其他人也会读到这篇文章。除了IsSpecialName和检查set_前缀(运算符有op_,event subscr./remov.有add_,remove_)外,您还可以检查方法是否与以下任何属性方法匹配:

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