2

Can we use Unity interception/extensions/custom proxy to perform this?

// psuedo-code
using (var childContainer = new container.CreateChildContainer())
using (var scope = new TransactionScope())
{
  childContainer.Resolve<TMyService>().PerformCall(...);
  scope.Complete();
}

Currently the above code is implemented as a WCF behaviour. We now have classes that access this service layer directly rather then making WCF calls and need this behaviour. The interesting part is we need to create a child container inside the unity interception.

Brian Low
  • 11,605
  • 4
  • 58
  • 63
  • This looks weird. I guess you are using child containers to dispose the object graph created inside the using statement? So you want to ensure a proper cleanup? I know that Castle Windsor wanted to [remove that feature](http://kozmic.pl/2010/06/01/castle-windsor-and-child-containers/) and I must say that Unity better should do that as well. You are using the container as a service locator which is [never a good idea](http://blog.ploeh.dk/2010/02/03/ServiceLocatorIsAnAntiPattern.aspx). – Sebastian Weber Nov 02 '12 at 06:48
  • 1
    Windsor wants to nuke child containers because they were an afterthought and never really designed. Unity had the idea of child containers from the start, and I don't see a reason they should be removed. Having said that, I agree the desired behavior doesn't sound like a good idea. – Chris Tavares Nov 04 '12 at 18:55
  • @ChrisTavares The only scenario I see for child containers is to create a limited lifetime scope (like per-web-request) that properly cleans up on its disposal. But I think that should the domain of LifetimeManagers (and resolved object tracking) and does not justify the child containers. What usage scenario did you have in mind when you designed that feature? – Sebastian Weber Nov 05 '12 at 20:43
  • There are two scenarios - first, lifetime scope (which lifetime managers later grew to handle) and the differential config, where you have the standard config in the parent container and you change just the things you care about in the child. – Chris Tavares Nov 05 '12 at 21:29
  • @SebastianWeber Yes, we want to limited lifetime scope. Currently it is per-web-request (more specifically it is per-business-transaction) but we now have callers that do not enter through the WCF interface. – Brian Low Nov 05 '12 at 22:17
  • @ChrisTavares So one scenario (lifetime scope) is obsolete and the other sounds like it can be solved by the ["include semantics for config"](http://entlib.uservoice.com/forums/89245-enterprise-library-6-0-unity-3-0/suggestions/2377298-provide-include-semantics-for-config) and ["enhanced config"](http://entlib.uservoice.com/forums/89245-enterprise-library-6-0-unity-3-0/suggestions/1672387-enhanced-configuration-for-unity) ideas on the Unity vNext wishlist. Or is there more to the second scenario? – Sebastian Weber Nov 06 '12 at 06:35

2 Answers2

2

Yes. I don't see why you couldn't. However...

although the use of interception often loosens the need to have a clean and SOLID design, when you want to do this, you still need a SOLID design.

I've written about these kind of designs that enable this here, and what it comes down to is that you will have model the operations you want to wrap behind a design, such as an ICommandHandler<T> with a Handle(T) method. With such a design, you can create a decorator (or in Unity's case an interceptor) that wraps a real class with a class that adds a child container like this:

public class ChildContainerCommandHandlerDecorator<T>
    : ICommandHandler<T>
{
    private readonly ICommandHandler<T> decorated;
    private readonly Container container;

    public ChildContainerCommandHandlerDecorator(
        ICommandHandler<T> decorated, Container container)
    {
        this.decorated = decorated;
        this.container = container;
    }

    public void Handle(T command)
    {
        using (container.CreateChildContainer())
        {
            this.decorated.Handle(command);
        }
    }
}

And a decorator that adds a transaction scope like this:

public class TransactionCommandHandlerDecorator<T>
    : ICommandHandler<T>
{
    private readonly ICommandHandler<T> decorated;

    public TransactionCommandHandlerDecorator(
        ICommandHandler<T> decorated)
    {
        this.decorated = decorated;
    }

    public void Handle(T command)
    {
        using (var scope = new TransactionScope())
        {
            this.decorated.Handle(command);

            scope.Complete();
        }
    }
}

By wrapping real handlers in both decorators, you can extend handlers with this behavior. Of course, decorators is a concept that Unity is unable to handle, but you can easily rewrite this using interceptors when working with Unity, but again, good design is your only friend here.

Steven
  • 166,672
  • 24
  • 332
  • 435
  • Thanks for the insight Steve, I didn't see the connection to the command pattern. I like it and have used it in the past. At the moment we aren't using a command pattern so I was hoping to leverage unity to consider each method call a "command". – Brian Low Nov 05 '12 at 22:22
  • 1
    Unity can handle decorators. It just needs a little help with the concept. Have a look at [Jim Christophers extension](http://www.beefycode.com/post/Decorator-Unity-Container-Extension.aspx). – Sebastian Weber Nov 06 '12 at 07:18
  • @Sebastian: Nice. Does this work for generic decorators as well? – Steven Nov 06 '12 at 09:11
  • @BrianLow: Chris, the developer behind Unity, seems to indicate that doing this would be "hideously slow" with Unity. If that's the case, and this is the design you prefer, try switching to a faster framework. – Steven Nov 06 '12 at 09:18
  • @Steven The extension uses default BuildKeys so I think it should be able to handle generics as well. But I never tested that scenario. – Sebastian Weber Nov 06 '12 at 10:05
  • @SebastianWeber: That yould be a great feature for your contrib project. However, why don't leave Unity and come with us to the dark side ;-) – Steven Nov 06 '12 at 10:33
  • @Steven It's already in ;) I guess by "the dark side" you mean the SimpleInjector project? I'll have a look at the code. – Sebastian Weber Nov 06 '12 at 11:10
  • @SebastianWeber: With the dark side I mean "crazy extensibility and performance tuning by doing expression trees rewriting". There's only one container I know that works this way, and yes... that's Simple Injector :-D – Steven Nov 06 '12 at 11:27
  • @Steven How do we ensure that injected "decorated" property uses child container? – Dzendo Nov 20 '17 at 13:11
0

No, I don't see a way you could do this. You could do the TransactionScope part, but the resolve/call part I just don't see working.

Well, I guess you could get it to work. You'd need a dummy instance of TMyService (or whatever object you're intercepting), and your interception behavior would need to do a bunch of reflection to figure out the type to grab, resolve it, and use reflection again to invoke the specific method. It could be done, but it would be hideously slow.

I'm not going to provide code for this, because I don't think it's a good idea. What scenario are you trying to implement with this - there's probably an easier way to accomplish it.

Chris Tavares
  • 29,165
  • 4
  • 46
  • 63
  • Thanks Chris. Our presentation layer accesses our domain by calling a service layer. This service layer is exposed as WCF services. We now have clients that bypass the WCF layer and call the service layer directly. – Brian Low Nov 05 '12 at 22:21