This project is read-only.

How to register two different database connections?

Jun 24, 2013 at 1:20 PM
In my current project, I need to use two different databases for different entities. All code that accesses the database is located inside command and query handlers that are implemented in the DAL.

Right now, those handlers have a dependency on NHibernate's ISession.

I now need to find a way to provide those handlers with a session to the correct database.

After some playing with RegisterWithContext I decided to use a different approach:
  1. I create two empty interfaces that inherit ISession, one per database, e.g. public interface IDictionarySession : ISession { }
  2. The implementations of those interfaces are simple decorators of ISession without any additional functionality besides implementing my derived interface.
  3. The handlers no longer depend on ISession but on one of the interfaces we just created.
  4. Registration is changed from one registration for ISession to two registrations - one per interface we created.
This approach seems to be pretty clean, easily configurable and with the added benefit that the handlers communicate clearly what database they need to access.
However, that approach has one severe draw back: Any decorators that also depend on a database session (like the decorator that automatically sets the mod user and mod date on all modified entities) will have to be created twice. Once for each interface deriving from ISession...

What do you think about that approach? How would you solve that requirement?
Jun 24, 2013 at 2:32 PM
Having an unique interface for database model is generally a good solution, because it removed ambiguity. Another advantage is that those interfaces can have extra members that make database communication easier. Take for instance a 'Orders' property that maps to the 'orders' table in the database. Such approach is not possible with a generic abstraction, since you'll pollute the abstraction with entities that not always available.

Although I seem to see the implementations of those implementations as decoractors, they probably are not, since the goals of a decorator is to add behavior, without changing the contract, while in fact you are changing the contract. It's unlikely that you register these implementations using the RegisterDecorator overloads, since they require the contract to stay in tact.

But since already seem to have decorators in place extending the behavior of ISession, you can keep using them. Your DictionarySessionImpl depends on ISession and at runtime a decorated session is injected into the DictionarySessionImpl. The registration might look like this:
container.Register<ISession>(() => factory.CreateSession(), new PerWebRequestLifestyle());
container.RegisterDecorator(typeof(ISession), typeof(ModUserSessionDecorator));
container.RegisterDecorator(typeof(ISession), typeof(ModDateSessionDecorator));

container.Register<IDictionarySession, DictionarySessionImpl>();
container.Register<IShippingSession, ShippingSessionImpl>();
Jun 24, 2013 at 2:49 PM
Edited Jun 24, 2013 at 3:02 PM
Thanks for your answer.

Unfortunately, I have the feeling it is missing the point a bit.
ISession is conceptually a wrapper around a database connection. With that in mind, it should be clear that the sample code at the end of your answer doesn't solve my initial problem: Supporting two different databases.

My current registration looks like this:
var factory = new SessionFactoryFactory();
var wawiSessionFactory = factory.Create(wawiConnectionString);
var dictionarySessionFactory = factory.Create(dictionaryConnectionString);
container.RegisterLifetimeScope<IWawiSession>(
    () => new WawiSession(wawiSessionFactory.OpenSession()));
container.RegisterLifetimeScope<IDictionarySession>(
    () => new DictionarySession(dictionarySessionFactory.OpenSession()));
And a command handler could look like this:
public class RenameTouchTerminalCommandHandler :
    ICommandHandler<RenameTouchTerminalCommand>
{
    private readonly ISession _session;
    public RenameTouchTerminalCommandHandler(IWawiSession session)
    {
        if(session == null) throw new ArgumentNullException("session");
        _session = session;
    }

    public override void Handle(RenameTouchTerminalCommand command)
    {
        var terminal = _session.Load<TouchTerminal>(command.TouchTerminalId);
        terminal.Name = command.NewName;
        _session.Update(terminal);
    }
}
Does this make the question clearer?

In general, I would be interested in how you would solve the requirement to access two different databases with distinct entities (e.g. one database for the normal domain entities and one database for translation related entities).
Jun 24, 2013 at 3:55 PM
Can you show how you currently set up the decorators (such as the user mode and date mod)?
Jun 24, 2013 at 4:00 PM
Sure. The implemention of that decorator looks like this:
public class ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand> : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> _decorated;
    private readonly ITouchTerminalContext _thisTerminal;
    private readonly ISession _session;

    public ModifiedEntitiesUpdaterCommandHandlerDecorator(
        ICommandHandler<TCommand> decorated, ISession session, ITouchTerminalContext thisTerminal)
    {
        if (decorated == null)
            throw new ArgumentNullException("decorated");
        if (session == null)
            throw new ArgumentNullException("session");
        if (thisTerminal == null)
            throw new ArgumentNullException("thisTerminal");
        _decorated = decorated;
        _session = session;
        _thisTerminal = thisTerminal;
    }

    public override void Handle(TCommand command)
    {
        _decorated.Handle(command);
        foreach (var modifiedEntity in
            Session.GetSessionImplementation()
                   .PersistenceContext.EntitiesByKey.Select(x => x.Value)
                   .OfType<IModifyable>()
                   .Where(x => Session.IsDirtyEntity(x)))
        {
            modifiedEntity.ModUser = _thisTerminal.Name;
            modifiedEntity.ModDate = DateTime.Now;
        }
    }
}
Registration looks like this:
        container.RegisterDecorator(
            typeof(ICommandHandler<>), 
            typeof(ModifiedEntitiesUpdaterCommandHandlerDecorator<>), 
            OnlyForNHibernateCommandHandler);
Jun 24, 2013 at 4:09 PM
Ahh.. okay, your decorators are wrapped around command handlers.

What you can do is injecting both IDictionarySession and IWawiSession into the ModifiedEntitiesUpdaterCommandHandlerDecorator. Downside is that this gets ugly when you get more databases. In that case you can register all sessions as a collection and let the decorator depend on that collection:
container.RegisterAll<ISession>(typeof(IDictionarySession), typeof(IWawiSession));
The decorator can become something like this:
public class ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand> 
    : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> _decorated;
    private readonly ITouchTerminalContext _thisTerminal;
    private readonly IEnumerable<ISession> _sessions;

    public void Handle(TCommand command)
    {
        _decorated.Handle(command);
        
        this.ModifySessions();
    }
    
    private void ModifySessions()
    {
        foreach (var session in _sessions)
        {
            this.ModifySession(session);
        }
    }
    
    private void ModifySession(ISession session)
    {
        var modifiedEntities = session.GetSessionImplementation()
           .PersistenceContext.EntitiesByKey.Select(x => x.Value)
           .OfType<IModifyable>()
           .Where(x => session.IsDirtyEntity(x));
    
        foreach (var modifiedEntity in modifiedEntities)
        {
            modifiedEntity.ModUser = _thisTerminal.Name;
            modifiedEntity.ModDate = DateTime.Now;
        }
    }
}
Any better?
Jun 24, 2013 at 4:22 PM
Edited Jun 24, 2013 at 4:24 PM
Yepp, now we are talking about the same problem :-)

Your suggestion would work, but it has two downsides:
  1. It will open sessions to all databases, not just to the one needed.
  2. It will potentially modify entities from a session that is not relevant to the decorated handler. However, this is a minor downside as this decorator is wrapped around all handlers anyway.
I think the first downside is a real problem. But I can't think of an easy solution, because the decorator would need to know about the session that has been created for the decorated handler. In principal, this is already working, because of the usage of a lifetime scope. But in this concrete case, it is not working, because the lifetime scope has been registered for IWawiSession and not for ISession.

Basically, the flow should be like this:
  1. Resolve ICommandHandler<SomeCommand>
  2. Implementation (SomeCommandHandler) requires an IWawiSession instance. Resolve it.
  3. Create instance of SomeCommandHandler with resolved IWawiSession instance.
  4. Command handlers are decorated by ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand>.
  5. Decorator depends on ICommandHandler<SomeCommand>: Use created instance of SomeCommandHandler.
  6. Decorator depends on ISession: **Use instance of IWawiSession from current lifetime scope. This is the instance that has been resolved in step 2.**
Step 6 is the important one. Is it possible to somehow achieve this?
Jun 24, 2013 at 10:04 PM
It will potentially modify entities from a session that is not relevant to the decorated handler.
But what if a handler directly or indirectly depends on two different sessions? Or does that never happen?
Is it possible to somehow achieve this?
You could do something like this:
container.RegisterLifetimeScope<Lazy<IWawiSession>>(
    () => new Lazy<IWawiSession>(
        () => new WawiSession(wawiSessionFactory.OpenSession())));

container.RegisterLifetimeScope<IWawiSession>(
    () => container.GetInstance<Lazy<IWawiSession>>().Value);

container.RegisterLifetimeScope<Lazy<IDictionarySession>>(
    () => new Lazy<IDictionarySession>(
        () => new DictionarySession(dictionarySessionFactory.OpenSession())));
        
container.RegisterLifetimeScope<IDictionarySession>(
    () => container.GetInstance<Lazy<IDictionarySession>>().Value);
And have a decorator like this:
public class ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand> 
    : ICommandHandler<TCommand>
{
    private readonly ICommandHandler<TCommand> _decorated;
    private readonly ITouchTerminalContext _thisTerminal;
    private readonly Lazy<IWawiSession> _wawiSession;
    private readonly Lazy<IDictionarySession> _dictionarySession;

    public void Handle(TCommand command)
    {
        _decorated.Handle(command);
        
        this.ModifySessions();
    }
    
    private void ModifySessions()
    {
        if (_wawiSession.IsValueCreated)
        {
            this.ModifySession(_wawiSession.Value);
        }
        
        if (_wawi_dictionarySessionSession.IsValueCreated)
        {
            this.ModifySession(_dictionarySession.Value);
        }
    }
    
    private void ModifySession(ISession session)
    {
        var modifiedEntities = session.GetSessionImplementation()
           .PersistenceContext.EntitiesByKey.Select(x => x.Value)
           .OfType<IModifyable>()
           .Where(x => session.IsDirtyEntity(x));
    
        foreach (var modifiedEntity in modifiedEntities)
        {
            modifiedEntity.ModUser = _thisTerminal.Name;
            modifiedEntity.ModDate = DateTime.Now;
        }
    }
}
This isn't the most prettiest thing, but it does do the trick because of the use of Lazy<T>.IsValueCreated. This prevents creating the instance if it isn't created already.

Another option is to analyze the dependency graph, but IMO that's quite nasty.

This is currently the best I can think of (after a long workday).
Jun 25, 2013 at 10:16 AM
Edited Jun 25, 2013 at 10:17 AM
Thanks for taking the time to think my issue through, even after a long workday.
I don't really like sacrificing the design of the decorator because of the way Simple Injector works, so the approach with injecting all Lazy<ISomeSession> into the decorator is not an approach I would like to take. Especially, because the decorator simply should work on the current session and that is a singular - only one session is open in the context of any given command handler.

I solved this problem by leaving my decorator as is - having a single ISession dependency - and moving the code with Lazy to the composition root:
container.RegisterLifetimeScope(() => new Lazy<IWawiSession>(() => new WawiSession()));
container.RegisterLifetimeScope(() => new Lazy<IDictionarySession>(() => new DictionarySession()));
container.RegisterLifetimeScope(() => container.GetInstance<Lazy<IWawiSession>>().Value);
container.RegisterLifetimeScope(() => container.GetInstance<Lazy<IDictionarySession>>().Value);
container.Register<ISession>(
    () =>
    {
        var wawiSession = container.GetInstance<Lazy<IWawiSession>>();
        var dictionarySession = container.GetInstance<Lazy<IDictionarySession>>();
        if (wawiSession.IsValueCreated)
        {
            if (dictionarySession.IsValueCreated)
                throw new InvalidOperationException("Multiple sessions have been opened.");
            return wawiSession.Value;
        }

        if (dictionarySession.IsValueCreated)
            return dictionarySession.Value;

        throw new InvalidOperationException("No session has been opened.");
    });

container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>), typeof(Program).Assembly);
container.RegisterDecorator(typeof(ICommandHandler<>), typeof(CommandHandlerDecorator<>));

Works like a charm :-) Thanks a lot!
Jun 25, 2013 at 11:49 AM
That's a nice solution. One warning about this approach though. You are now implicitly depending on a particular order of the constructor arguments of your decorator. This approach will fail when you move the ISession dependency before the ICommandHandler<TCommand> dependency. In that case ISession will be resolved first and your delegate will throw an exception because neither Lazy<IWawiSession>.IsValueCreated nor Lazy<IDictionarySession>.IsValueCreated will be true.

To mitigate this, you can change the ISession registration to an Lazy<ISession> and call value in the Handle method of your decorator (after the building of the object graph is done).

Here is another idea. Perhaps you are able to determine using the application's metadata which session should be used in which command handler. For instance, perhaps you already grouped commands or their command handlers in a certain namespace (or assembly) based on their database or some related criteria.

In that case you can (again) use the RegisterWithContext extension method with a registration as follows:
container.RegisterLifetimeScope<IWawiSession>(() => new WawiSession());
container.RegisterLifetimeScope<IDictionarySession>(() => new DictionarySession());
    
container.RegisterDecorator(typeof(ICommandHandler<>),
        typeof(ModifiedEntitiesUpdaterCommandHandlerDecorator<>));
    
container.RegisterWithContext<ISession>(context =>
{
        Type commandType = context.ServiceType.GetGenericArguments().Single();
        
        if (commandType.Namespace.EndsWith("Wawi")) {
                return container.GetInstance<IWawiSession>();
        } else if (commandType.Namespace.EndsWith("Dictionary")) {
                return container.GetInstance<IDictionarySession>();
        } else {    
            throw new InvalidOperationException("No handling for " + commandType.FullName);
        }
});
Another option is to the decorator conditionally. This saves you having to make the extra ISession registration, but forces you to make a specific decorator for each session. Here's an example:
container.RegisterLifetimeScope<IWawiSession>(() => new WawiSession());
container.RegisterLifetimeScope<IDictionarySession>(() => new DictionarySession());
container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(WawiModifiedEntitiesUpdaterCommandHandlerDecorator<>),
    c => c.ServiceType.GetGenericArguments().Single().Namespace.EndsWith("Wawi"));    
    
container.RegisterDecorator(
    typeof(ICommandHandler<>),
    typeof(DictionaryModifiedEntitiesUpdaterCommandHandlerDecorator<>),
    c => c.ServiceType.GetGenericArguments().Single().Namespace.EndsWith("Dictionary"));
Both decorators can derive from an abstract ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand, TSession>, which minimized the amount of code they need:
public class WawiModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand> 
    : ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand, IWawiSession>
{
    public WawiModifiedEntitiesUpdaterCommandHandlerDecorator(
        ICommandHandler<TCommand> decorated, ITouchTerminalContext thisTerminal,
        IWawiSession session) : base(decorated, thisTerminal, session) { }
}

public class DictionaryModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand> 
    : ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand, IDictionarySession>
{
    public WawiModifiedEntitiesUpdaterCommandHandlerDecorator(
        ICommandHandler<TCommand> decorated, ITouchTerminalContext thisTerminal,
        IDictionarySession session) : base(decorated, thisTerminal, session) { }
}

public class ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand, TSession> 
    : ICommandHandler<TCommand>
    where TSession : ISession    
{
    private readonly ICommandHandler<TCommand> _decorated;
    private readonly ITouchTerminalContext _thisTerminal;
    private readonly TSession _session;

    public void Handle(TCommand command)
    {
        _decorated.Handle(command);
        
        this.ModifySession();
    }
    
    private void ModifySession() { ... }
}
Another downside of this is that we now miss the extra validation that we implemented in the RegisterWithContext method (the third case). We could implement this using a third decorator though:
container.RegisterDecorator(typeof(ICommandHandler<>),
    typeof(WawiModifiedEntitiesUpdaterCommandHandlerDecorator<>), c =>
    {
        Type commandType = c.ServiceType.GetGenericArguments().Single();
        if (!commandType.Namespace.EndsWith("Wawi") &&
            !commandType.Namespace.EndsWith("Dictionary"))
        {
            throw new InvalidOperationException("No handling for " +
                commandType.FullName);
        }
        return false; // never use this decorator. Just for validation.
    });
It would however be cooler if we would be able to do this:
// WARNING: Will not work
var decoratorType = typeof(ModifiedEntitiesUpdaterCommandHandlerDecorator<,>);

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    decoratorType.MakeGenericType(
        decoratorType.GetGenericArguments().First(),
        typeof(IWawiSession)),
    c => c.ServiceType.GetGenericArguments().Single().Namespace.EndsWith("Wawi"));  

container.RegisterDecorator(
    typeof(ICommandHandler<>),
    decoratorType.MakeGenericType(
        decoratorType.GetGenericArguments().First(),
        typeof(IDictionarySession)),
    c => c.ServiceType.GetGenericArguments().Single().Namespace.EndsWith("Dictionary"));
In other words, register a partial generic type definition for the ModifiedEntitiesUpdaterCommandHandlerDecorator<TCommand, TSession> (with just one of the generic parameters to filled in).

This however does not work, because Simple Injector (or any other DI framework that I know of btw) does not support registering partially generic type definitions.
Jun 25, 2013 at 12:41 PM
You are now implicitly depending on a particular order of the constructor arguments of your decorator.
That's a pity. I thought that resolution would work in a way that first resolves the "actual" handler and only afterwards its decorators.
Implicitly depending on that order is something I would like to avoid, basically making the current solution unusable.
Using Lazy<ISession> in the decorator again bleeds implementation details of Simple Injector into it.

The approach with RegisterWithContext is what I initially tried to do, but I was unable to combine it with the lifetime scope.
The motivation of combining it is the following:
Assume that the actual command handler depends on IWawiSession, although the command is declared in the Dictionary namespace. (That in itself would probably be a bug, but that's not really the issue here)
This would result in the decorator getting another session as the actual command handler.

The approach with multiple decorators - one per session type - is again attributed to the design of Simple Injector and thus something I would like to avoid.

I think the preferred approach would be to revert to the original design:
Even the concrete command handlers depend only on ISession and the database connection to be used is determined by some attribute of the command (like the namespace).
Registration in this case would be simple (apart from the fact that it is not working right now):
container.RegisterWithContext<ISession>(context =>
{
        Type commandType = context.ServiceType.GetGenericArguments().Single();
        
        if (commandType.Namespace.EndsWith("Wawi")) {
                return _wawiSessionFactory.OpenSession();
        } else if (commandType.Namespace.EndsWith("Dictionary")) {
                return _dictionarySessionFactory.OpenSession();
        } else {    
            throw new InvalidOperationException("No handling for " + commandType.FullName);
        }
}, LifetimeScopeLifestyle.Get(true));
This doesn't work, because RegisterWithContext has no overload that accepts a lifestyle. It always uses the transient lifestyle internally. That's easy to fix.
The bigger problem is that LifetimeScopeLifestyle.Get is internal. I could use the public constructor of that class but I am unsure if this is a good idea. I recon there was a good reason for making the static fields and the get method internal and for using static fields in the first place.

Is it ok to use the constructor? What do you think about that approach in general?
Jun 25, 2013 at 1:34 PM
That's a pity. I thought that resolution would work in a way that first resolves the "actual" handler and only afterwards its decorators.
If you think about it, it's quite obvious. When you're doing this by hand, you'll get code like this:
var wawiSession = new Lazy<IWawiSession>(() => new WawiSession());

Func<ISession> session = () =>
{
    if (wawiSession.IsValueCreated) return wawiSession.Value;
    throw Exception("No session.");
};

var handler = new ModifiedEntitiesUpdaterCommandHandlerDecorator<MyCommand>(
    new MyCommandHandler(
        wawiSession.Value,
        new SomeOtherDependency()),
    session.Value);
In C#, when calling a constructor, the method arguments are evaluated from left to right and because of this, you would find that this code has the same side effect; swapping the decorator's contructor arguments will make the code fail. So the problem is not Simple Injector specific, and I would even say that the order in which arguments are evaluated is an implementation detail. When compiling down expression trees to IL, Simple Injector does not use C#. .NET Expression trees or the .NET runtime happens to evaluate the arguments from left to right, but I'm not sure that this is even documented. My advice: don't rely on this.
Using Lazy<ISession> in the decorator again bleeds implementation details of
Simple Injector into it.
Don't forget that your current solution with Lazy<IWawiSession> as the same 'bleeding' as a solution with Lazy<ISession>.
That in itself would probably be a bug, but that's not really the issue here
You could write a unit test that verifies this. My preference is usually to have a DI configuration that can be verified by calling Container.Verify without having to use extra unit tests, if possible.
is again attributed to the design of Simple Injector and thus something
I would like to avoid.
I understand you try to prevent letting limitations of your DI container influence your application design. That's a good general goal. For that same reason you shouldn't want to decorate constructors with a (Ninject) [Inject] attribute, or let types depend a (Autofac) Owned<T>.

To mitigate this, place your derived decorators inside the composition root. They will become infrastructor components and not part of the application code. They don't contain any logic to test anyway, so this is no problem. The base class contains logic, and you might want to test this. This base class can be part of your application if you wish.
RegisterWithContext has no overload that accepts a lifestyle.
That is deliberate. The normal use case for RegisterWithContext is to return different instances based on its context (parent information for instance). While building a single object graph, there will often be multiple different parents this dependency must be injected into, and each parent might get a different instance. If all parents should get the same instance, you could already register this using the WebRequestLifestyle, LifetimeScopeLifestyle, WcfOperationLifestyle, etc. In other words, caching the instance returned by RegisterWithContext would defeat the purpose of that method.

Instead of trying to change the RegisterWithContext method, you can redirect the registration to other registrations, as I showed in my previous answer:
if (commandType.Namespace.EndsWith("Wawi")) {
        return container.GetInstance<IWawiSession>();
} else ... etc
You can cache the registrations for IWawiSession and IDictionarySession per lifetime scope. This way the RegisterWithContext can stay transient; the actual returned objects are lifetime scoped.
Is it ok to use the constructor? What do you think about that approach in general?
The internal LifetimeScopeLifestyle.Get(bool) method is just an optimization that prevents the RegisterLifetimeScope extension methods from creating a new LifetimeScopeLifestyle instance per registration. But this is just an optimization in memory use and there is no difference with creating many LifetimeScopeLifestyle instances (the only state such instance contains is whether they should dispose or not).
Jun 25, 2013 at 2:18 PM
dot_NET_Junkie wrote:
That's a pity. I thought that resolution would work in a way that first resolves the "actual" handler and only afterwards its decorators.
If you think about it, it's quite obvious. When you're doing this by hand, you'll get code like this:
var wawiSession = new Lazy<IWawiSession>(() => new WawiSession());

Func<ISession> session = () =>
{
    if (wawiSession.IsValueCreated) return wawiSession.Value;
    throw Exception("No session.");
};

var handler = new ModifiedEntitiesUpdaterCommandHandlerDecorator<MyCommand>(
    new MyCommandHandler(
        wawiSession.Value,
        new SomeOtherDependency()),
    session.Value);
It is not so obvious. You could also write it like this:
var actualHandler = new MyCommandHandler(
        wawiSession.Value,
        new SomeOtherDependency());
var handler = new ModifiedEntitiesUpdaterCommandHandlerDecorator<MyCommand>(actualHandler, session.Value);
That's what I thought SI was doing to avoid the problem with the order of the decorators constructor parameters.
I agree that the order of constructor parameter evaluation is an implementation detail, making the case for the proposed implementation stronger:
  1. Create the inner most instance, i.e. the decorated instance
  2. Wrap it with the decorator that has been registered first
  3. Wrap the result with the next decorator
  4. And so on.
This is possible and sensible, because SI knows about the hierarchy because of the way the container is registered.
Using Lazy<ISession> in the decorator again bleeds implementation details of
Simple Injector into it.
Don't forget that your current solution with Lazy<IWawiSession> as the same 'bleeding' as a solution with Lazy<ISession>.
In my current solution, only the Composition Root is using Lazy<T>. None of the application code uses Lazy<T> because of needs by SI. And that's exactly how I want to keep it.
That in itself would probably be a bug, but that's not really the issue here
You could write a unit test that verifies this. My preference is usually to have a DI configuration that can be verified by calling Container.Verify without having to use extra unit tests, if possible.
I don't see how you would ever achieve something like this if the registration is not trivial. For example, you need unit tests to verify the correct order of decorators.
is again attributed to the design of Simple Injector and thus something
I would like to avoid.
I understand you try to prevent letting limitations of your DI container influence your application design. That's a good general goal. For that same reason you shouldn't want to decorate constructors with a (Ninject) [Inject] attribute, or let types depend a (Autofac) Owned<T>.
Agreed, relying on Owned<T> wasn't the best idea, but at least, that was explicit. Using Lazy<T> because of the way SI wires up decorated instances is everything but explicit.
To mitigate this, place your derived decorators inside the composition root. They will become infrastructor components and not part of the application code. They don't contain any logic to test anyway, so this is no problem. The base class contains logic, and you might want to test this. This base class can be part of your application if you wish.
I assume you are refering to the derived decorators per session. My main problem with this approach is the additional code that shouldn't be necessary in the first place.
RegisterWithContext has no overload that accepts a lifestyle.
That is deliberate. The normal use case for RegisterWithContext is to return different instances based on its context (parent information for instance). While building a single object graph, there will often be multiple different parents this dependency must be injected into, and each parent might get a different instance. If all parents should get the same instance, you could already register this using the WebRequestLifestyle, LifetimeScopeLifestyle, WcfOperationLifestyle, etc. In other words, caching the instance returned by RegisterWithContext would defeat the purpose of that method.
Good point.
Instead of trying to change the RegisterWithContext method, you can redirect the registration to other registrations, as I showed in my previous answer:
if (commandType.Namespace.EndsWith("Wawi")) {
        return container.GetInstance<IWawiSession>();
} else ... etc
That still assumes the usage of IWawiSession and IDictionarySession. However, in my last post, I came to the conclusion that it would be better to get rid of them. The reason was that there might be a discrepancy between the namespace of the command and the type of the command handlers session parameter.
If SI would support named registrations, this would be really simple:
container.RegisterLifetimeScope<ISession>(() => _wawiSessionFactory.OpenSession(), "WAWI");
container.RegisterLifetimeScope<ISession>(() => _dictionarySessionFactory.OpenSession(), "Dictionary");
container.RegisterWithContext<ISession>(context =>
{
        Type commandType = context.ServiceType.GetGenericArguments().Single();
        
        if (commandType.Namespace.EndsWith("Wawi")) {
                return container.GetInstance<ISession>("WAWI");
        } else if (commandType.Namespace.EndsWith("Dictionary")) {
                return container.GetInstance<ISession>("Dictionary");
        } else {    
            throw new InvalidOperationException("No handling for " + commandType.FullName);
        }
}
But that's not possible - at least not readily - so I need to find a different solution.
Jun 25, 2013 at 3:12 PM
I don't see how you would ever achieve something like this if the registration is not trivial.
You can't avoid it, and the container can't verify whether your configuration is sensible, only that object graphs can be composed. But certain configurations increase the need for unit tests. Everything that is not resolved during object graph build time for instance (Lazy<T>, Func<T>, factories, etc) can't be verified by the container and you'll need tests for this. I always try to minimize the need for these constructs if I possible. But again, it's not always possible, but the more I can lean on the the verification of the object graph, the happier I am :-)
If SI would support named registrations, this would be really simple
With Simple Injector you can do this which has the same result:
var lifestyle = new LifetimeScopeLifestyle();

var wawiProducer = new InstanceProducer(typeof(ISession),
    lifestyle.CreateRegistration<ISession>(
        () => _wawiSessionFactory.OpenSession(), container));

var dictProducer = new InstanceProducer(typeof(ISession),
    lifestyle.CreateRegistration<ISession>(
        () => _dictionarySessionFactory.OpenSession(), container));

container.RegisterWithContext<ISession>(context =>
{
    Type commandType = context.ServiceType.GetGenericArguments().Single();

    if (commandType.Namespace.EndsWith("Wawi")) {
        return (ISession)wawiProducer.GetInstance();
    } else if (commandType.Namespace.EndsWith("Dictionary")) {
        return (ISession)dictProducer.GetInstance();
    } else {
        throw new InvalidOperationException("No handling for " + commandType.FullName);
    }
});
The two created InstanceProducer instances are in fact your 'named registrations', although they are not registered in the container by a key; they're named in your source code.
Marked as answer by dot_NET_Junkie on 3/2/2014 at 10:45 AM
Jun 26, 2013 at 12:44 PM
dot_NET_Junkie wrote:
With Simple Injector you can do this
Yes, that's exactly what I was looking for all along!

Thanks a lot :-)