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

发布于 2024-07-05 01:33:51 字数 727 浏览 8 评论 0原文

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

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

I've got a custom handler applied to a class (using the Policy Injection Application Block in entlib 4) and I would like to know whether the input method is a property when Invoke is called. Following is what my handler looks like.

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

As you can see from my code sample, the best way I've thought of so far is by parsing the method name. Isn't there a better way to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

明月夜 2024-07-12 01:33:51

虽然有点晚了,但其他人也会读到这篇文章。 除了 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;

It is a bit late but other people will read this too. In addition to IsSpecialName and checking for the set_ prefix (operators have op_, event subscr./remov. has add_,remove_) you can check if method is a match to any of properties methods like this:

    bool isProperty = method.ReflectedType.GetProperties().FirstOrDefault(p => 
        p.GetGetMethod().GetHashCode() == method.GetHashCode() 
        || p.GetSetMethod().GetHashCode() == method.GetHashCode())!=null;
落在眉间の轻吻 2024-07-12 01:33:51

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

You could check the IsSpecialName property; it will be true for property getters and setters. However, it will also be true for other special methods, like operator overloads.

﹎☆浅夏丿初晴 2024-07-12 01:33:51

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

MSDN 上的 System.Reflection.MethodBase.IsSpecialName

I'm not familiar with that application block, but assuming that MethodBase property is of type System.Reflection.MethodBase, you could take a look at the IsSpecialName property.

System.Reflection.MethodBase.IsSpecialName on MSDN

亢潮 2024-07-12 01:33:51

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

A couple of you mentioned using the "IsSpecialName" property of the MethodBase type. While it is true that the will return true for property "gets" or "sets", it will also return true for operator overloads such as add_EventName or remove_EventName. So you will need to examine other attributes of the MethodBase instance to determine if its a property accessor. Unfortunately, if all you have is a reference to a MethodBase instance (which I believe is the case with intercepting behaviors in the Unity framework) there is not real "clean" way to determine if its a property setter or getter. The best way I've found is as follows:

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
你与清晨阳光 2024-07-12 01:33:51

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

You can also check IsSpecialName is true. this will be true in a property (amongst other things)

At the il level the methods are exposed as follows (using Environment.ExitCode as example):

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

If you wanted to get fancy you could verify after extracting the name that said property exists but to be honest

if (m.IsSpecialName && (m.Attributes & MethodAttributes.HideBySig) != 0)) 

as well as starts with get_ or set_ then you should be good even for people using nasty names (faking the hidebysig is easy enough, faking the IsSpecialName would be very tricky)

Nothing is guaranteed though. Someone could emit a class with a set_Foo method that looked just like a real set method but actually wasn't a set on a read only property.
Unless you check whether the property CanRead/CanWrite as well.

This strikes me as madness for you though you aren't expecting deliberate circumvention.
A simple utility/extension method on MethodInfo which did this logic wouldn't be too hard and including IsSpecialName would almost certainly cover all your needs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文