This project is read-only.

Missing Child Container - How to deal with it?

Feb 15, 2015 at 1:00 PM
Hello,

currently we are using in our project Unity as DI Container. Influenced by several blog posts I fancy with the idea to migrate to Simple Injector.

Because we have already a wrapper around the actual DI Container most of the migration should be pretty strait forward.

But there is one major topic where I have problems to see a solution:
Unity supports Child-Container - and we are using them.

AFAIK Simple Injector does not support Child Container. I am pretty sure there are good reasons for it.

My challenge is now, how to deal with it :)

I suppose that it is possible to solve our problems without Child-Container.
But currently I have no good idea - which is the reason for this post.

Here some details how and why we are using Child-Container:
  1. There are some parts of our object-graph which should have a "local" singleton.
    Example: In one area of our program the same database instance shall be used.
    • This area is resolved within one bigger resolve
    • This area creates dynamically new objects via the DI-Container (Command pattern)
  2. It is required to resolve an interface in the "main" DI-Container.
    The implementation of this interface needs a rather complex object graph.
    Therefore a lot of other registrations are required to instantiate this subgraph.
    • It is important that this subgraph reuses globally registered "singletons"
    • But some required registrations are just valid inside of the subgraph
      and should not be visible to the outer world (main DI Container)
      (e.g. singleton - see point one, or selected implementation of an interface )
I think these are the most important reasons of our child-container usage.

Are there any standard solutions for this type of problems / requirements?
How to deal with them without child container?

With best regards,
stefan
Feb 15, 2015 at 2:08 PM
The reason that Simple Injector does not support child containers is because:
  • Child containers are very performance heavy, which does not fit Simple Injector's strategy to be fast by default.
  • Promotes composition root scattering, because child containers are often configured on a per-request basis, making it harder to maintain and grasp the registration part of your application.
  • Simple Injector promotes the notion of having an immutable container, while child containers promote the notion of making and chancing registrations at any point in time. This doesn't match with our overall design philosophy.
  • Makes it impossible for Simple Injector to supply you with useful diagnostic results, because parts of the registrations are done at a later point in time.
  • For some containers (such as Unity), using child containers are the mechanism to created components with a scoped lifestyle (using the HierarchicalLifetimeManager if I'm not mistaken). In Unity, registering instances per-web-request, simply means creating a child container and having that instance registered as singleton within that child container (hierarchical). Simple Injector on the other hand has the notion of scoped lifestyles to do this.
Your question is quite broad, which makes it hard to be very specific, but I'll try to explain how to 'do things' in Simple Injector. In general however, I haven't come across a scenario that requires child containers at all.

The first thing that struck me however when reading your question is that I suspect a violation of the Liskov Substitution Principle in your application. Perhaps I completely misinterpreted how your application looks, but it seems as if you have one part (area) of your application that uses a different database than the other parts do, while all application code uses the same abstraction. I could vision you having some sort of IUnitOfWork which is registered globally to the CentralDatabaseUnitOfWork, while that particular area gets a UserManagementUnitOfWork implementation.

Again, perhaps I'm completely wrong, but if this is the scenario, you can't really blame Simple Injector for not getting this right. You are violating the Liskov Substitution Principle (LSP), one of the 5 SOLID principles. What the basically says is that any subtype (CentralDatabaseUnitOfWork and UserManagementUnitOfWork) of the same abstraction (IUnitOfWork) should be interchangeable for one another, without breaking the application. For instance, if you have an ILogger abstraction with DatabaseLogger and FileLogger implementations, you should be able to swap implementations around, without consumers of ILogger to know anything about it. Clients should not care to what destination the log is written (if ever written), but swapping those implementations around should not cause any consumer to break. But this will clearly happen if you inject a CentralDatabaseUnitOfWork in code that expects to work with the user management database, because they both have a completely different database schema. If on the other hand you swap databases that contain an identical schema, swapping implementations will not be a problem, and will not break the consuming code.

According to the LSP this is a problem, and in fact it is a problem, because you will see that these violations make your DI configuration much harder. Forget about Simple Injector for a moment; it makes registration more complex, no matter what container you use. And it makes the code more complex, because just by looking at the abstraction, you don't know which implementation you expect. You find out which implementation you expect by looking at the code that uses it. You will see lines of code like from user in this.UnitOfWork.Repository<User>() where ....

The solution is often simple. If both implementations are not interchangable, they should not be part of the same abstraction. So give each implementation its own abstraction, such as IUserManagementUnitOfWork and ICentralDatabaseUnitOfWork. This completely removes the ambiguity that you have in your DI registration, because now you don't need to have a different registration for a certain area. You just register both implementations accordingly:
container.Register<IUserManagementUnitOfWork, UserManagementUnitOfWork>();
container.Register<ICentralDatabaseUnitOfWork, CentralDatabaseUnitOfWork>();
But okay, this assumption was a bit an educated guess. Or well.. not really educated, but I shoot myself in the foot by doing this wrong in the past multiple times, so let's say it's an experienced guess, or painful foot guess :-)

At a high level, I think there are three ways how apply this kind of scoping in Simple Injector:

Scoped lifestyles
The most common way is to use scoped lifestyles. Most of the time the lifestyle of such 'child singleton' instance is within a quite clearly defined scope. Usually this is around a request, such as a web request, timer pulse of a windows service, or directly after the user pushes a button in a desktop application. Simple Injector contains quite a few scoped lifestyles, such as Web Request, Web API Request, Per WCF Operation, Lifetime Scope, and Execution Context Scope. All of those lifestyles make use of the SimpleInjector.Scope class, which could be seen as the child container container part, with the exception that you can't make registrations in a scope. It's just a cache. Some of the scoped lifestyles manage this scope implicitly for you (such as Web Request, Web API Request and WCF Operation), while others force you to explicitly begin and dispose such scope (these are Lifetime Scope and Execution Context Scope), just as you would do when you call BeginChildContainer() in Unity.

So if such instance must live during such clearly defined request, use one of the Scoped Lifestyles.

Multiple Containers
Another options is to define multiple containers. This is something you can do when your application runs multiple modules that contain a high level of isolation. In this case you can see each module as its own application, but you just happen to run them in the same app domain. In that scenario it makes sense to give each module its own container instance and optionally have one extra container instance for the 'shell' application that forwards calls to the modules. This is actually something we do in the application I'm working on right now. Do note most applications should be considered a module on their own, and thus you should have only one container in such application. When you talk about an 'area' however, this might sound like something that lives in isolation.

Splitting up an existing application in modules however, can be daunting. Often there are quite some shared dependencies that you need to split or move to a shared library. In our application we have a shell container and five module containers, and all six containers share some services that are registered as 'application wide singleton'. The trick here is simply to manually new up those singletons and register them as instance in all containers. Pro tip: nobody ever said that all components should be auto-wired by your container.

Custom Scopes
Simple Injector allows you to create your own scope and own scoped lifestyle. For instance, you can create a lifestyle such as a 'per area lifestyle', but it implementation depends on your exact needs. Since I'm not completely sure about your requirements, I'm unable to be very specific in how to write such lifestyle.
Feb 15, 2015 at 2:44 PM
Edited Feb 16, 2015 at 10:04 PM
Hello,

thanks for the fast answer.

Sorry for the rough and misleading description of my problem. I hope this post will clarify some aspects.
I understand the reasons behind the design decision of Simple Injector (and many other DI Containers).

I think we don't violate "Liskov Substitution Principle". I guess my simplified description was misleading.
As I mentioned the database my intention was just the instance of the same type.

The (simplified) reason is that the relevant interface has a notion of views. Where an area should share the same view on the database.
Another example would be a notion of documents. Where an area of the software should share the same document. Therefore all resolves in an specific area of the software should use the same instance because it is related to a document on the disc. In the same time other parts of the software using a different document.

I hope this explains better my intention.

Currently I am just planning to configure a DI-Container just once. Therefore during the startup there is a phase where the DI Container is configured but not used
and later there is the phase where the DI Container is just used to resolve interfaces and is not changed.
Also the Child containers are created statically.

If I understand your Scoped lifestyles correctly that it is like a cache. Therefore the scoped lifecycle is the rule whenever instances are created or reused.
If my understanding is correct, I have the following challenges to face:
  • Several areas of our software (different UIs, different viewmodels, models) are dealing with a single document and accessing the document is done via interfaces which are resolved. Therefore I have to create a custom Scoped-Lifestyle for the document-access interface.
    I have to find a solution how to create and use the right custom scoped-lifestyle in each area.
    Something like
           "The resolving of this interface IToolAreaA should use this scoped lifestyle for IDocumentAccess interface"
       and "The resolving of this interface IToolAreaB should use this scoped lifestyle for IDocumentAccess interface"
    
  • Is it possible to have several scoped-lifestyles at the same time? In my example:
    IToolAreaA should share the same instance for the document access interface. As an example: ToolAreaA has Import and Export functionality.
    Both dealing therefore with sub-dialogs, directories, etc. Now I want that both using the same IDocumentAccess-Instance but Import has an own notion of current directory (and export an own too).
I think I need an understanding how custom scopes are used.


Update:
I read and debugged following example:
https://simpleinjector.readthedocs.org/en/2.7/lifetimes.html#customlifestyles
(e.g. "Absolute 10 Minute Expiration")

My problem is:
The decision if a new scope should be created and not depends whenever I am part of an area.
(e,g, ToolAreaA or ToolAreaB)

One idea would be:
Each Area must implement a specific interface (e.g. INewDatabaseAccessScope).
Then my CustomLifestyle implementation have to check whenever the currently resolved object is part of the object graph below of an type implementing INewDatabaseAccessScope...

Another idea would be:
I want to provide extra information to my Registration of "ToolAreaA". Whenever such an object is created (independent how) I want to get "notified".
  • Begin (I would say: Now a new custom scope begins)
  • End (I would say: Now the existing custom scope ends)
With best regards,
Stefan
Feb 15, 2015 at 6:56 PM
Edited Feb 16, 2015 at 8:53 PM
I think you pretty much understand what lifestyles do. As I said, the Scope object they use under the covers is much like the caching behavior of a child container. After reading your last response I do think that a custom lifestyle might be best in your case.

A custom lifestyle is easily created. Here's an example of a special 'area lifestyle':
public sealed class AreaLifestyle : ScopedLifestyle
{
    // Define the global scopes you need in the application.
    public static readonly Scope Area1 = new Scope();
    public static readonly Scope Area2 = new Scope();

    [ThreadStatic]
    private static Scope currentScope;

    public AreaLifestyle() : base("Area") { }

    public static Scope CurrentScope { get { return currentScope; } }

    public static IDisposable UseScope(Scope scope) {
        var cleaner = new ScopeCleaner(currentScope);
        currentScope = scope;
        return cleaner;
    }

    protected internal override Func<Scope> CreateCurrentScopeProvider(Container container) {
        return () => currentScope;
    }

    // Return a value just lower than singleton. This is crucial for good diagnostic messages.
    protected override int Length { get { return 999; } }

    private sealed class ScopeCleaner : IDisposable {
        private readonly Scope parentScope;
        private bool disposed;
        public ScopeCleaner(Scope parentScope) { this.parentScope = parentScope; }
        public void Dispose() {
            if (!this.disposed) {
                currentScope = this.parentScope;
                this.disposed = true;
            }
        }
    }
}
Here we define a custom AreaLifestyle that uses a scope instance that is stored in a thread-static private field. You can register instances with this lifestyle as follows:
var areaLifestyle = new AreaLifestyle();

container.Register<IDocumentAccess, DocumentAccess>(areaLifestyle);
container.Register<ISomethingElse, SomethingElse>(areaLifestyle);
And when resolving an object graph from the container, you will now have set the correct scope from which those instances should be resolved:
using (AreaLifestyle.UseScope(AreaLifestyle.Area1)) {
    var handler = container.GetInstance<ICommandHandler<ShipOrder>>();
    handler.Handle(command);
}
Let me know how this works out for you.
Feb 15, 2015 at 7:43 PM
Edited Feb 16, 2015 at 10:04 PM
I got the idea, but have a problem... My areas are implicitly created because a much higher class gets the areas injected.
Example:
public class ApplicationMainComponent : IAppicationMainComponent
{
   pubic ApplicationMainComponent(ISubCompA compA, ISubCompB compB) {...}
}

public class SubCompA : ISubCompA
{
   pubic SubCompA (IAreaLeft left1, IAreaRight right) {...}
}
There is pretty much just one GetInstance:
container.GetInstance<IAppicationMainComponent>()
Maybe I am a little bit slow but I have problems to use the using statement around the relevant Area...

Or is the solution something like:
container.Register<IAreaLeft>(  () => 
  {
        using (AreaLifestyle.UseScope(AreaLifestyle.Area1))
        {
           container.GetInstance<AreaLeft>();
        }
  }
  );
Therefore the AreaLeft instance is resolved inside of the using block.
If this is the right way I can simplify the solution by:
  • I need no "named" access to the Areas... Something like a stack would work well (this would also support nested areas :) )
  • It is possible to implement a generic AreaLifestyle which could be based on the attributes of the actual resolved type
I will play with the idea...

Thanks a lot.
Feb 15, 2015 at 7:52 PM
But if you resolve the ApplicationMainComponent from the main container, how exactly did you solve this with child containers in Unity? It seems to me that in this case everything is resolved.through the main container. Can you show an example of how you are doing this with Unity. Hopefully I get a good grasp of ehat you are really achieving here and I might be able to assist you better.
Feb 15, 2015 at 8:31 PM
Edited Feb 16, 2015 at 10:05 PM
Hm...

Very similar to the solution based on lifestyle.
container.Register<IAreaLeft>(  () => 
  {
        var childContainer = container.CreateChildContainer(); // Inherit the standard configuration
  
        // Area local singletons are registered
        // Also the real implementation of "IAreaLoeft" is registered
        ConfigureContainerWithSpecificsForAreaLeft(childContainer);

        // Just the child container has the registration for the IAreaLeft implementation
        childContaine.GetInstance<IAreaLeft>();
  );
Feb 16, 2015 at 5:42 PM
Edited Feb 16, 2015 at 7:53 PM
Update:

based on the example I have now an working solution.
  • Thanks a lot *
But there are still two open issues:
  1. Some of my services have to be disposed.
    => I read that Simple Injector has per design a limited support for IDisposable...
    I will check it...
  2. In some of my areas I have to resolve instances dynamically (e.g. a command for a unit of work).
    If such a command is resolved as part of a area it should follow the area specific AreaLifestyle.
    => Therefore I have to capture the current Scope Configuration. This configuration must later be restored during command resolving.
I will no work on the second issue.

stefan
Feb 16, 2015 at 9:05 PM
About your issues:

(issue 1) Out of the box, Simple Injector only disposes instances for scoped lifestyles (that is basically everything but transient and singleton). The plan is to support disposing singletons in v3, but transient objects will never be tracked (and disposed) by Simple Injector. So disposing basically happens on the boundary of a scope, and Simple Injector allows registering objects for disposal, and allows code to be notified when the scope ends, allowing objects to do some clean up.

If you however have singletons that need to be disposed, you can either do this manually, or use the code that is shown here. When you need instances disposed that are singleton-per-area, this is just a matter of disposing the scopes, when the application ends, just as you would do with child containers:
AreaLifestyle.Area1.Dispose();
AreaLifestyle.Area2.Dispose();
(issue 2) This depends a bit on what and how your instances are resolved at a later point in time, but if you designed your application using something like this, it should be as easy as applying a decorator or other part of infrastructure. I see two options here:
  1. either you store/inject the scope of the active Area in the infrastructure class (decorator/factory/mediator) so that you can use that scope during resolving the service at a later point in time.
  2. You determine the proper scope based on the command that is executed.
Here's an example of option 1:
// Define some decorator that stores the scope upon creation:

public class AreaAwareCommandHandlerDispatcher : ICommandHandlerDispatcher
{
    private readonly Scope activeScope;
    private readonly Container container;

    public CommandHandlerDispatcher(Container container) {
        this.activeScope = AreaLifestyle.CurrentScope;
        this.container = container;
        Requires.IsNotNull(this.activeScope, "AreaLifestyle.CurrentScope");
    }

    public void Handle<TCommand>(TCommand command) {
        using (AreaLifestyle.UseScope(this.activeScope)) {
            var handler = container.GetInstance<ICommandHandler<TCommand>>();
            handler.Handle(command);
        }
    }
}
Note that I made a small adjustment to the AreaLifestyle that I posted in a previous comment. Please scroll up to see this update. This decorator would normally be part of your Composition Root.

Here's an example of option 2:
public class AreaAwareCommandHandlerDispatcher : ICommandHandlerDispatcher
{
    private readonly Container container;

    public CommandHandlerDispatcher(Container container) {
        this.container = container;
    }

    public void Handle<TCommand>(TCommand command) {
        Scope scope = typeof(TCommand).Namespace.Contains("Area1") ? AreaLifestyle.Area1 : AreaLifestyle.Area2;
        using (AreaLifestyle.UseScope(scope)) {
            var handler = container.GetInstance<ICommandHandler<TCommand>>();
            handler.Handle(command);
        }
    }
}
If you were using child containers of a different container, I would expect to see similar code as given above.
Feb 17, 2015 at 7:51 PM
Edited Feb 17, 2015 at 7:54 PM
About the issues:
  1. Disposing. I need no disposing of transient objects. But for singletons and scoped lifetimes.
    => So I am looking forward for v3, or a workaround would be to create an own scope which will just be disposed at the end of the application :)
  2. I looked into your solutions. Currently I prefer the first one where the scope is injected into the class where the dynamic resolving is needed.
    This is also very similar to our current solution which is based on unity child containers.

    In the Child Container, the container itself (more exactly a small resolve facade) is registered.
    Translated into Lifetimes: The combination of the container-resolve-logic and the relevant scope is one entity and is also resolvable.
I will create a prototype based on your first solution and will perform an update to the post if there is something (interesting) to post :)
The main topic to support lazy resolving is to create a snapshot of the current scope and to restore it in case of lazy resolving.
(In your solution the constructor of the CommandHandlerDispatcher which stores both, the container and the current scope)

From my perspective when I compare our current solution to the discussed one:
  1. Child Container:
    • I don't need the ability to perform registrations in a child container.
    • I like that child containers are one entity which combines the container with the scope.
      This entity can be resolved to perform lazy creation of objects
  2. Discussed solution:
    • I like the idea to simplify the container by avoiding unneeded features. Which could also lead to better performance.
    • I don't like that the current scope/area is managed outside of the container and is not part of the execution flow (e.g. resolving)
      => This leads to the ThreadStatic-Members to support multi-threading (btw: which is required in our use cases)
Motivated by this discussion I come to the following observations:
  • It seems for me that most DI containers support scoping based on the outer world (e.g. Threads, WCF, ...)
  • It seems for me that it becomes tricky if the resolved object tree self is the reason of the scoping.
The second point leads to several interesting aspects:
  • Creating a scope depending on the currently resolved type muyst be implemented by something like:
    (A delegate is registered which creates the scope and then performs the resolving of the actual type)
        public static void RegisterWithNewArea<TService, TImplementation>(this Container container)
            where TService : class
            where TImplementation : class, TService
        {
            container.Register<TService>(() =>
            {
                var areas = typeof (TImplementation).GetCustomAttributes<CreateAreaAttribute>().Select(attribute => attribute.AreaId).ToList();
                using (AreaLifestyle.PushAreas(areas))
                {
                    return container.GetInstance<TImplementation>();
                }
            });
        }
I don't know the consequences but I would like to be able to add this extra stuff as part of the registration. Something like a Func<IResovlingState, IDisposable>. 
So that my Func is able to store some extra information in a ResolvingState and returns a disposable. 
  • Because the current scope/area is managed outside of the container and outside of resolving execution path the relevant information must be stored
    in static / Thread-Local Variables.
protected internal override Func<Scope> CreateCurrentScopeProvider(Container container) {
        return () => currentScope;
    }
I don't know the consequences but I would like to have an extra argument in the CreateCurrentScopeProvider which belongs to the current resolve.
(e.g. IResolvingState)

The Func could store some graph / resolve depending information into the IResolveState which can later be used in the CreateCurrentScopeProvider to decide which scope is the right one.
  • To avoid creating a snapshot of the current scope and to restore it manually following would be nice:
    A method on the Container which returns an entity consists of two parts: The container itself and the current ResolvingState. So that this returned interface can be
    used and also injected into the graph (with the current scope so that the CreateCurrentScopeProvider works as it would be in the same resolve call).
The IResolvingState could be very simple. Maybe just a simple key/value pair storage (similar to a Dictionary).

Maybe my current conclusions are too shallow and too complicated. Therefore feedback is welcome...

stefan