我有一个应用于类的自定义处理程序(使用 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; }
}

正如您从我的代码示例中看到的,到目前为止我想到的最好方法是解析方法名称。难道没有更好的方法吗?

有帮助吗?

解决方案

您还可以检查 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 几乎肯定会满足您的所有需求。

其他提示

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

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

MSDN 上的 System.Reflection.MethodBase.IsSpecialName

你们中的一些人提到使用 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

虽然有点晚了,但其他人也会读到这篇文章。除了 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;
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top