How to delay(lazy creation) or suppress creation of Call Handler objects until the method is actually called

Oct 7, 2014 at 11:59 PM
I am trying to use Interception Call Handler and Handler Attributes on my interfaces (or implementation). Lets say my Interface has two methods DoSomething() and DoSomethingElse(), and I only have the interceptor for DoSomethingElse(); when I resolve my main interface the constructor for the Call Handler get called even if I never invoke DoSomethingElse().

I tried this by resolving to Lazy(of IMainInterface) but the moment I call the function DoSomething() the Call Handler is still created unnecessarily. Is there a way to prevent this from happening either by code or configuration.

Here is my sample implementation
<AttributeUsage(AttributeTargets.Method)>
Public Class NormalSampleAttribute
    Inherits HandlerAttribute
    Public Sub New()
        Console.WriteLine("Constructor of Normal Sample Attribute")
    End Sub

    Public Overrides Function CreateHandler(container As Microsoft.Practices.Unity.IUnityContainer) As Microsoft.Practices.Unity.InterceptionExtension.ICallHandler
        Console.WriteLine("Create Handler")
        Return New SampleCallHandler
    End Function
End Class

Public Class SampleCallHandler
    Implements ICallHandler
    Public Sub New()
        Console.WriteLine("Constructor of Sample Call handler")
    End Sub

    Public Function Invoke(input As IMethodInvocation, getNext As GetNextHandlerDelegate) As IMethodReturn Implements ICallHandler.Invoke
        Console.WriteLine("Invoke  of Sample Call handler - " & input.MethodBase.Name)
        Return getNext.Invoke(input, getNext)
    End Function
    Public Property Order As Integer Implements ICallHandler.Order
End Class

Public Interface IMainInterface
    Sub DoSomething()
    <NormalSample()>
    Sub DoSomethingElse()
End Interface

Public Class MainClass
    Implements IMainInterface

    Public Sub New()
        Console.WriteLine("main class - Constructor")
    End Sub

    Public Sub DoSomething() Implements IMainInterface.DoSomething
        Console.WriteLine("main class do something...")
    End Sub

    Public Sub DoSomethingElse() Implements IMainInterface.DoSomethingElse
        Console.WriteLine("main class do something else...")
    End Sub
End Class


Module Module1
    Public container As IUnityContainer
    Sub Main()
        container = New UnityContainer
        DoRegistrations()
        Console.WriteLine("Before lazy  Resolve")
        Dim lmc As Lazy(Of IMainInterface) = container.Resolve(Of Lazy(Of IMainInterface))()
        Console.WriteLine("Before making lazy function call")
        lmc.Value.DoSomething()
        Console.ReadLine()
    End Sub

    Sub DoRegistrations()
        container.AddNewExtension(Of InterceptionExtension.Interception)()
        container.RegisterType(Of IMainInterface, MainClass)()
        container.Configure(Of Interception).SetDefaultInterceptorFor(Of IMainInterface)(New InterfaceInterceptor)
    End Sub
End Module
It produces the following output:

Before lazy Resolve
Before making lazy function call
main class - Constructor
Constructor of Normal Sample Attribute
Create Handler
Constructor of Sample Call handler

main class do something...


Even though DoSomethingElse() is never called the cost of the handler creation is being added on all flows. Is there any way to avoid this? Any help is appreciated.

Thanks in advance!
SV
Oct 8, 2014 at 5:25 AM
I don't think there is a way to defer creation of the handlers. Unity creates the pipeline when creating the proxy object.

One approach is to create the call handler as a singleton. This way the same call handler instance will be used for all objects.

<AttributeUsage(AttributeTargets.Method)>
Public Class NormalSampleAttribute
    Inherits HandlerAttribute
    Public Sub New()
        Console.WriteLine("Constructor of Normal Sample Attribute")
    End Sub

    Public Overrides Function CreateHandler(container As Microsoft.Practices.Unity.IUnityContainer) As Microsoft.Practices.Unity.InterceptionExtension.ICallHandler
        Console.WriteLine("Create Handler")
        Return container.Resolve(Of ICallHandler)(GetType(SampleCallHandler).Name)
    End Function
End Class

container.RegisterType(Of ICallHandler, SampleCallHandler)(GetType(SampleCallHandler).Name, New ContainerControlledLifetimeManager())

This approach might not work if the attribute needs to pass in different state (e.g. Properties) to the call handler for each use.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Oct 8, 2014 at 6:18 PM
@Randy
Thanks for the reply. I understand your approach for singleton can be used in certain cases, but unfortunately for my situation we do have attributes. And also I am not sure if I want another container.Resolve to address performance issues we identified, where unity buildup for these attributes is taking the majority of time/cpu.

One other approach we are evaluating is using caching to cache instances already created for a set of parameter values.

Regards

SV
Oct 8, 2014 at 6:40 PM
Yes, caching might be a good approach in this case. I thought about mentioning it in the context of Unity (e.g. a named, registered singleton per parameter set) but in the CreateHandler method you would have to query the container (which is going to be even more expensive!) or reference a global container in the attribute constructor (which is not a nice design).

You might also want to look at changing the interceptor type; perhaps a Virtual Method Interceptor would be faster. Of course, that also affects the design since interceptable methods must be virtual.

There is also the option of changing Unity's internal implementation depending how far down the rabbit hole you want to go.


~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Oct 9, 2014 at 12:07 AM
Assuming I chose to go down the "rabbit hole", can you point me in the right direction as to where I need to change this implementation?

I also tried setting my registrations to singletons, even then each resolve creates new instances of the attributes and call handlers while returning the already created instance for my concrete implementation.

One approach we are evaluating is to split the interfaces and keep the implementation same in one class. I noticed that only attributes defined in each of the smaller interfaces are only getting created which saves a lot at the moment.

Thanks

SV