Standalone Interception and Method Call Injection

Jul 13, 2010 at 10:00 AM
Hi, I'm trying out interception to implement INotifyPropertyChanged on my entities. Currently going the standalone interception route and the using "container.BuildUp" to do the injection. The interception bit works fine, but it seems like Method injection does not happen on the intercepted class? Any ideas? Thanks, D
Jul 14, 2010 at 1:27 AM

You mean when you call the BuildUp method, it doesn't perform method injection?  Could you post the sample code repro?

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Jul 14, 2010 at 8:37 AM
I've created a sample project illustrating the problem - how / where can I upload? Thanks. D.
Jul 14, 2010 at 9:12 AM

You can send it in entlib.support@avanade.com.  If the code isn't that long, you can just post it here.

Jul 14, 2010 at 10:00 AM
Thx - sent the email!
Jul 14, 2010 at 10:52 AM

You only need to modify the call to BuildUp :

_iocContainer.BuildUp(type, result);

In addition, you don't need to register the container to itself, that is automatically being done for you.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

Jul 14, 2010 at 11:53 AM
Thanks
Aug 20, 2010 at 3:13 PM
AvanadeSupport wrote:

You only need to modify the call to BuildUp :

_iocContainer.BuildUp(type, result);

In addition, you don't need to register the container to itself, that is automatically being done for you.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com

I think I am having a similar if not identical problem.

When I use the container to create the method interception works fine but when I use container.BuildUp() on an existing instance the interception does not take place.

The code is based on Lab 3 of the Enterprise Library 5.0 Hands On Labs.  Just wish the labs included using an example of using existing instance.

When the commented off line is used rather than the one below it interception takes place fine.

Thanks in advance,

        private BusinessLogic.BankAccount bankAccount;
        private IUnityContainer container;

        public MainForm()
        {
            InitializeComponent();
            InitializeContainer();
            PopulateUserList();
//            bankAccount = container.Resolve<BusinessLogic.BankAccount>();
            bankAccount = new BusinessLogic.BankAccount();
            container.BuildUp(bankAccount.GetType(), bankAccount);
        }

        private void InitializeContainer()
        {
            container = new UnityContainer();
            container.AddNewExtension<Interception>();
            container.RegisterType<BusinessLogic.BankAccount>(
                new Interceptor<VirtualMethodInterceptor>(),
                new InterceptionBehavior(new TraceBehavior(new TraceSource("interception"))));
        }

 

Aug 20, 2010 at 5:32 PM

You have two problems. The first is that VirtualMethodInterceptor only works when creating a new instance. When you think about the implementation, that makes sense - the way the interception is hooked up is to dynamically generate a subclass of the type you're intercepting, override all the virtual methods on that type, and the implementation of these overridden methods invoke the behaviors. C# is not Python, Ruby, or Javascript, so if the instance is already created we're stuck - we can't recreate the object out from under you.

You can do interception on an existing instance if you use one of the other two interceptors - TransparentProxy or Interface. Those interceptors use a separate proxy object which run the behaviors before calling your actual object. In that case, you will need to capture the return value:

  bankAccount = container.BuildUp(bankAccount.GetType(), bankAccount);

so that you're now calling the proxy instead of the real object.

I realize it's confusing, but there are a lot of tradeoffs here. This is why we have different interceptors; because there's no one technique that guarantees you can intercept everything all the time in all circumstances.

Anyway, I hope that helps.

 

Aug 20, 2010 at 7:02 PM

It does help, Thank you!

With the code below it works.  I am working with the CSLA.NET 4 framework and am deriving from its base classes to extend them.  The base classes do not inherit from MarshalByRefObject so as I understand it I cannot use the TransparentProxyInterceptor.  I will try using existing framework interface(s) that have the methods I want to intercept or define new interfaces that contain the methods that I want to intercept.

When stepping through the Unity code encountered in the code below I saw references to not supporting open generics.  Since generics are in play, I hope that this means that as long as all of the generic type parameters have been provided in the class/type where interception is desired that it can work with it.

Thanks again for helping a Unity beginner get started,

        private IBankAccount _iBankAccount;
        private BusinessLogic.BankAccount _bankAccount;
        private IUnityContainer _container;

        public MainForm()
        {
            InitializeComponent();
            InitializeContainer();
            PopulateUserList();
            _bankAccount = new BusinessLogic.BankAccount();
            _iBankAccount = _container.BuildUp<IBankAccount>(_bankAccount);
        }

        private void InitializeContainer()
        {
            _container = new UnityContainer();
            _container.AddNewExtension<Interception>();
            _container.RegisterType<IBankAccount, BusinessLogic.BankAccount>(
                new Interceptor<InterfaceInterceptor>(),
                new InterceptionBehavior(new TraceBehavior(new TraceSource("interception"))));
        }

Aug 20, 2010 at 8:10 PM

My understanding has improved with this exercise but I think I may not be able to attain my final objective.

Since the framework base classes I am interested in take control of instance creation I cannot use VirtualMethodInterceptor.  Since those same framework base classes do not inherit from MarshalByRefObject I cannot use TransparentProxy.  If I use InterfaceInterceptor I have no way of getting the framework to call the object returned from Container.BuildUp().  The framework will continue to call on the object it created rather than the one returned by Container.BuildUp().  I can use the object returned from Container.BuildUp() for my calls I do not see how I can take advantage of that.

My objective was to do add logging using interception so that I did not have to pollute the main logic with it and to keep the logging very loosely coupled.

Is this as a fatal blow to my objective?

Since it is an open source framework I could modify the framework source for my needs but then I will be taking ownership of it making future versions costly to take advantage of.

Aug 21, 2010 at 11:00 PM

Unless there's a hook somewhere that lets you control how the framework creates objects, yeah, it sounds like you're out of luck.