4

I'm having object structure with depth of inheritance of 3. Object is implementing single particular interface. The depth of inheritance for interface is 4. My final object is being constructed via unity IoC. I need to intercept every public method in this object (means no matter in which of interfaces it is defined), though whatever interceptor type I use (InterfaceInterceptor/TransparentProxyInterceptor/VirtualMethodInterceptor ) it always intercepts only methods defined in the final class of inheritance tree. Please see the illustration of object structure below:

public interface IDevice {
    void Connect();
}

public interface ISerialDevice {
   void WriteCommand();
}

public interface IProtocolSerialDevice {
   void ExecuteProtocolCommand();
}

[MyHandler]
public interface ICustomSerialDevice {
   void ExecuteMyCommand();
}

public abstract class AbstractSerialDevice {
   public virtual void WriteCommand() {
        //omitted
   }
}

public abstract class AbstractProtocolSerialDevice : AbstractSerialDevice {
    public virtual void ExecuteProtocolCommand() {
         //omitted
    }
}


public class CustomSerialDevice : AbstractProtocolSerialDevice, ICustomSerialDevice {
      public virtual void ExecuteMyCommand() {
            //omitted
      }
}

public class MyHandlerAttribute : HandlerAttribute {
      public override ICallHandler CreateHandler(IUnityContainer container) {
         //omitted
      }
}

Object is registered into unity container as follows:

container.RegisterType<ICustomSerialDevice, CustomSerialDevice>(
   new ContainerControlledLifetimeManager(),  new InjectionMethod(postConstructMethodName));

container.Configure<Interception>()
         .SetInterceptorFor<ICustomSerialDevice>(new TransparentProxyInterceptor());

Unfortunately my interceptor always gets invoked only for ExecuteMyCommand() method. Is it possible to do such interception I'm striving for via unity container? I'm slowly thinking of trying to achieve it via Spring.NET AOP library.

TechCrap
  • 930
  • 3
  • 14
  • 28
  • Can you update your question and show how your object graph looks like (for instance, how would the code look like if you build this object graph by hand)? And what cross-cutting concerns are you trying to add? – Steven Dec 23 '14 at 08:33
  • Object graph is rather branchy as it depends on multiple objects which also depends on some others; class CustomSerialDevice is just a singleton object within scope of unity container, though it has multiple dependencies onto other objects, so by hand it might be something like new CustomSerialDevice {Dependency1 = new Dependency1 { Dependency2 = new Dependency2()}....}. Is this what you meant in your first question? I needed to do some general exception handling over each of CustomSerialDevice's methods(also inhereted ones) – TechCrap Dec 23 '14 at 11:25
  • Exactly, but I rather see you showing this with the actual names of the types. The thing is that I often see developers fall back on interception (compared to the use of decorators for instance) to apply cross-cutting concerns because of flaws in their design. If we can look at the design and how you try to apply those cross-cutting concerns, we might be able to feedback on the design. – Steven Dec 23 '14 at 11:34

1 Answers1

2

First off, I would recommend you use the InterfaceInterceptor wherever possible. It will give you the best flexibility and performance. Fall back to using VirtualMethodInterceptor when you can't use InterfaceInterceptor. And as a last resort, use TransparentProxyInterceptor. See here.

For interfaces, the handler attribute only applies to the methods defined on that interface (not inherited). So you can achieve what you are after by decorating all 4 interfaces with the [MyHandler] attribute.

For concrete classes, the handler attribute applies to all inherited types. So you can achieve what you are after by decorating the top AbstractSerialDevice with the [MyHandler] attribute. You could also decorate individual methods on either the interface or the concrete class level.

Also, in my opinion, decorating a concrete method is a bit more discoverable than decorating a type. Though it is a bit more verbose.


Option 1

// No MyHandler on any of the concrete classes

[MyHandler]
public interface IDevice
{ /* omitted */ }

[MyHandler]
public interface ISerialDevice : IDevice
{ /* omitted */ }

[MyHandler]
public interface IProtocolSerialDevice : ISerialDevice
{ /* omitted */ }

[MyHandler]
public interface ICustomSerialDevice : IProtocolSerialDevice
{ /* omitted */ }

Option 2

// No MyHandler on any of the interfaces nor derived classes

[MyHandler]
public abstract class AbstractSerialDevice : ISerialDevice
{ /* omitted */ }

Option 3

// No MyHandler on any of the interfaces nor abstract classes

public class CustomSerialDevice : AbstractProtocolSerialDevice, ICustomSerialDevice
{
    [MyHandler]
    public override void Connect()
    { base.Connect(); }

    [MyHandler]
    public override void WriteCommand()
    { base.WriteCommand(); }

    [MyHandler]
    public override void ExecuteProtocolCommand()
    { base.ExecuteProtocolCommand(); }

    [MyHandler]
    public void ExecuteMyCommand()
    { /*omitted*/ }
}

Any of those options work for you?

TylerOhlsen
  • 5,485
  • 1
  • 24
  • 39
  • 1
    I was a little surprised by this result, so thanks for pointing out something unexpected. Knowledge of these kind of quirks is valuable. – TylerOhlsen Dec 21 '14 at 04:18
  • 1
    Thanks for your great answer. Your third option works perfectly for me! – TechCrap Dec 22 '14 at 07:25