... Home Contact

Krzysztof Koźmic's blog

Designed in Poland, assembled in Australia.


Show appreciation: My Amazon.com Wish List


Me@Twitter

    Currently reading

    Article Categories

    Archives

    Post Categories

    MyPersonal

    Syndication:

    Castle Dynamic Proxy tutorial part III: Selecting which methods to intercept

    Welcome to the 3rd part of my Dynamic Proxy tutorial.

    If you’re new here, you may take a look at previous parts first

     

    We’ll start by updating our CallLoggingInterceptor class, so that we can use it in tests. What we need from it, is to enhance its functionality, so that it not only logs (to the Console) the calls, but also keeps a count of calls. To do that we add a property called Count, which gets incremented each time a method is called. It’s a trivial code, so I' won’t show it here.

    With that, we can now write our first test. We want property setters to fire tests for object freezability. Getters are safe in this regard and test always passes, so it’s an unnecessary overhead. We want our getters to not get intercepted, so let’s write a test for that.

    [Fact]
    public void Freezable_should_not_intercept_property_getters()
    {
        var pet = Freezable.MakeFreezable<Pet>();
        Freezable.Freeze(pet);
        var notUsed = pet.Age; //should not intercept
        var interceptedMethodsCount = GetInterceptedMethodsCountFor(pet);
        Assert.Equal(0, interceptedMethodsCount);
    }

    Let us not concern ourselves with GetInterceptedMethodsCountFor method just yet. For now let’s only say that it just does what its name suggests. We’ll inspect its implementation later. Now, we run the test, and – as expected, it fails.

    dptutorial_3_getter_failed_test

    So how do we make it pass? What we need is some kind of mechanism that will enable us to choose, which methods we want to intercept, and which we don’t. Fortunately Dynamic Proxy enables that. It exposes a hook that enables us to plug in into its proxy generation pipeline, in form of… IProxyGenerationHook interface (you wouldn’t guess, would you?).

    dptutorial_3_IProxyGenerationHook

    Two really interesting methods are NonVirtualMemberNotification, that enables us to act, when user wants to proxy a type that has some non-virtual methods i.e. methods we can’t intercept. We’ll concentrate on that method in the next part of the tutorial.

    What we need right now is ShouldInterceptMethod method, that enables us to decide whether we want to intercept a method or not. We know all we need, so let’s add a new class to our project, and implement the method, leaving two other methods empty just for now.

    public class FreezableProxyGenerationHook:IProxyGenerationHook
    {
        public bool ShouldInterceptMethod(Type type, MethodInfo memberInfo)
        {
            return !memberInfo.Name.StartsWith("get_", StringComparison.Ordinal);
        }
     
        public void NonVirtualMemberNotification(Type type, MemberInfo memberInfo)
        {
        }
     
        public void MethodsInspected()
        {
        }
    }

    OK, we have our proxy generation hook, but how do we actually hook into the pipeline? To do this we need to provide our hook to proxy generation method, so a good place to look is CreateClassProxy method on our generator. Indeed it has quite a few overloads.

    dptutorial_3_CreateClassProxyOverloads

    Some of them take additional parameter of type ProxyGenerationOptions, and this is exactly what we need. We will examine ProxyGenerationOptions class in details as we move through this tutorial, because it’s a very important class in advanced proxy related scenarios. Basically, as its name implies it’s a container for various options related to proxy generation process. As such it’s also used to pass out proxy generation hook to the proxy generator. We can pass our FreezableProxyGenerationHook as a constructor argument to ProxyGenerationOptions. We also need to cast generated object back to its type,as we’re using a non-generic version of CreateClassProxy now.

    public static TFreezable MakeFreezable<TFreezable>() where TFreezable : class, new()
    {
        var freezableInterceptor = new FreezableInterceptor();
        var options = new ProxyGenerationOptions(new FreezableProxyGenerationHook());
        var proxy = _generator.CreateClassProxy(typeof(TFreezable), options, new CallLoggingInterceptor(), freezableInterceptor);
        _freezables.Add(proxy, freezableInterceptor);
        return proxy as TFreezable;
    }

    With this change we can now see if our test passes…

     

    dptutorial_3_getter_passed_test

    …and it does, along with all other. Great. Now, our implementation takes care of property getters but how about all the other methods? Well they get intercepted too, which is not the desired behavior. To fix that, we need to slightly alter our ShouldInterceptMethod method to intercept only property setters

    public bool ShouldInterceptMethod(Type type, MethodInfo memberInfo)
    {
        return memberInfo.Name.StartsWith("set_", StringComparison.Ordinal);
    }

    (I did this in a test first manner, but I won’t bore you with screenshots of failed/passed tests. The tests however are in the attached code).

    If we run the program now, we’ll see that only setters get intercepted.

    dptutorial_3_program

    In the next part of the tutorial we’ll take care of cases when we can’t ensure objects state is never changed, and we’ll discuss the implementation of GetInterceptedMethodsCountFor method from our tests.

    In the meantime, if you have any questions use the “leave comment” feature of this blog, or ping me via GTalk, email or Skype.

    Code is here.

    Technorati Tags: , ,

    Feedback

    Gravatar

    # Can DynamicProxy used to intercept server side WCF objects?
    Scott_M | 4/26/2009 9:36 PM

    Can DynamicProxy used to intercept server side WCF objects?

    DynamicProxy appears to be more eloquent that WCF MessageInspection

    weblogs.asp.net/.../...-wcf-message-inspector.aspx



    Gravatar

    # re: Castle Dynamic Proxy tutorial part III: Selecting which methods to intercept
    Krzysztof Koźmic | 4/27/2009 11:22 AM

    @Scott

    Yes, it can, but you'd have to use another WCF' extension point - IInstanceProvider (msdn.microsoft.com/.../...r.iinstanceprovider.aspx) to inject proxied instance into Wcf ServiceHost.

    You don't have to do it manually though. In Castle project there is Windsor Facility that integrates Windsor with WCF, and it uses DynamicProxy for a lot of things it is doing.
    Gravatar

    # re: Castle Dynamic Proxy tutorial part III: Selecting which methods to intercept
    Miao Jack | 1/6/2010 8:03 AM

    hello Krzysztof Koźmic,
    I have downloaded the source of your articles
    like "cid-6e18e107780d3f4a.skydrive.live.com/.../6E18...!145", but I cannot upzip the files, can you give me a help?
    Gravatar

    # re: Castle Dynamic Proxy tutorial part III: Selecting which methods to intercept
    Aalano | 3/2/2010 8:33 PM

    hello, is there any planned support to retain the method's parameters' attributes in proxies?

    We're using ASP.Net mvc over here with a CustomModelBinderAttribute.
    Gravatar

    # re: Castle Dynamic Proxy tutorial part III: Selecting which methods to intercept
    Krzysztof Koźmic | 3/6/2010 12:34 AM

    @Aalano

    DP does replicate all non-inheritable attributes. So you should be able to access them on your proxies. If you're having problems with that go to castle users group on google groups and provide some more details.



    Comments have been closed on this topic.