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; }
}

从我的代码示例中可以看出,到目前为止我想到的最好的方法是解析方法名称。难道没有更好的方法来做到这一点吗?

4

5 回答 5

4

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

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

于 2008-09-16T15:58:19.127 回答
0

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

于 2008-09-16T15:42:58.630 回答
0

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

MSDN 上的 System.Reflection.MethodBase.IsSpecialName

于 2008-09-16T15:46:27.967 回答
0

你们中的一些人提到了使用 MethodBase 类型的“IsSpecialName”属性。虽然对于属性“gets”或“sets”确实会返回 true,但对于诸如 add_EventName 或 remove_EventName 之类的运算符重载,它也会返回 true。因此,您需要检查 MethodBase 实例的其他属性以确定它是否是属性访问器。不幸的是,如果您所拥有的只是对 MethodBase 实例的引用(我相信在 Unity 框架中拦截行为就是这种情况),那么就没有真正的“干净”方法来确定它是属性设置器还是获取器。我发现的最好方法如下:

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
于 2014-06-08T02:55:06.953 回答
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;
于 2016-10-19T10:02:28.260 回答