Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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.

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

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

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;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top