Repository SI wire up

Oct 25, 2013 at 2:29 AM
Hi, I'm having a problem wiring up repos, will you help?

The bootstrapper:
    public static class RepositoryBoostrapper
    {
        public static void Bootstrap(Container container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }
            container.RegisterOpenGeneric(
                typeof(IRepositoryQuery<>), 
                typeof(RepositoryQuery<>));

            container.RegisterOpenGeneric(
                typeof(IReadRepository<>),
                typeof(ReadRepository<>));
            container.RegisterOpenGeneric(
                typeof(IWriteRepository<>),
                typeof(WriteRepository<>));

            container.RegisterDecorator(
                typeof(IReadRepository<>),
                typeof(DecoratedReadRepository<>));
            container.RegisterDecorator(
                typeof(IWriteRepository<>),
                typeof(DecoratedWriteRepository<>));

            container.RegisterDecorator(
                typeof(DecoratedReadRepository<>),
                typeof(LoggingReadRepository<>));
            container.RegisterDecorator(
                typeof(DecoratedWriteRepository<>),
                typeof(LoggingWriteRepository<>));

            container.RegisterDecorator(
                typeof(DecoratedReadRepository<>),
                typeof(LoggingClientReadRepository<>)); <-- This is where at one of the issues is!
            container.RegisterDecorator(
                typeof(DecoratedWriteRepository<>),
                typeof(LoggingClientWriteRepository<>));
        }
    }
   public class LoggingReadRepository<TEntity> 
        : DecoratedReadRepository<TEntity> where TEntity : class
    {
        public LoggingReadRepository(IReadRepository<TEntity> readRepository) 
            : base(readRepository) { }
    public abstract class DecoratedReadRepository<TEntity> 
        : IReadRepository<TEntity> where TEntity : class
    {
        private readonly IReadRepository<TEntity> _readRepository;

        protected DecoratedReadRepository(IReadRepository<TEntity> readRepository)
        {
            _readRepository = readRepository;
        }
    public class LoggingClientReadRepository
        : DecoratedReadRepository<Tenant>
    {
        public LoggingClientReadRepository(IReadRepository<Tenant> readRepository)
            : base(readRepository) { }
Coordinator
Oct 25, 2013 at 10:55 AM
The problem is in your registration. You should change your registration to the following:
container.RegisterDecorator(typeof(IReadRepository<>), typeof(LoggingReadRepository<>));
container.RegisterDecorator(typeof(IWriteRepository<>), typeof(LoggingWriteRepository<>));
container.RegisterDecorator(typeof(IReadRepository<>), typeof(LoggingClientReadRepository<>));
container.RegisterDecorator(typeof(IWriteRepository<>), typeof(LoggingClientWriteRepository<>));
What you did was trying to chain decorators by pointing at the previous decorator, but this wont work. When applying decorators, Simple Injector will only look at the requested service type (since this is the only information that is available). Since you request an IReadRepository<T>, Simple Injector just checks if their are any decorators that should be applied to IReadRepository<T>, but all it finds is a decorator that should be applied to DecoratedReadRepository<T>, but since IReadRepository<T> is not a DecoratedReadRepository<T>, the LoggingClientReadRepository<T> will not get applied.

Decorator support is one of the areas where Simple Injector differs from other DI containers. With other DI containers, decorators will often have to point at a specific wrapped implementation, and that's very close to what you were doing. That model however has severe limitations, and the model that Simple Injector offers is both simpler and more flexible. For instance, take this configuration:
container.RegisterDecorator(typeof(IReadRepository<>), typeof(LoggingReadRepository<>),
    context => context.ImplementationType.Namespace.Contains("Admin"));
container.RegisterDecorator(typeof(IReadRepository<>), typeof(LoggingClientReadRepository<>));
In this configuration, the inner decorator is conditional, while the outer decorator is always applied (but note that conditional decoration is done under the covers for you when you apply generic type constraints). This allows the decorator chain to differ per T implementation. This is something that is very hard to do with the other DI containers.

So remember, always register a decorator for the service type you are resolving. You will never be requesting an DecoratedReadRepository<T>, but only the IReadRepository<T> abstraction.
Marked as answer by dot_NET_Junkie on 2/26/2014 at 1:20 PM
Oct 25, 2013 at 5:56 PM
I changed it up like you said, but the last two lines are still not compiling: Class 'Repository.Decorated.Logging.LoggingClientReadRepository' does not have type parameters

The RegisterDecorators:
container.RegisterDecorator(typeof(IReadRepository<>), typeof(LoggingReadRepository<>));
container.RegisterDecorator(typeof(IWriteRepository<>), typeof(LoggingWriteRepository<>));
container.RegisterDecorator(typeof(IReadRepository<>), typeof(LoggingClientReadRepository<Tenant>)); < - I added the Type in the Generic
container.RegisterDecorator(typeof(IWriteRepository<>), typeof(LoggingClientWriteRepository<Tenant>));
This is the Class once more for reference:
    public class LoggingClientReadRepository
        : DecoratedReadRepository<Tenant> <- Here I 'filled in' the type of the Generic
    {
        public LoggingClientReadRepository(IReadRepository<Tenant> readRepository)  <- Here I 'filled in' the type on the Generic
            : base(readRepository) { }
The Decorated abstract class again for reference:
    public abstract class DecoratedReadRepository<TEntity> 
        : IReadRepository<TEntity> where TEntity : class
Oct 25, 2013 at 6:35 PM
It seems to work when I take off the generic. The last two configuration lines:
            container.RegisterDecorator(typeof(IReadRepository<>), typeof(LoggingClientReadRepository));
            container.RegisterDecorator(typeof(IWriteRepository<>), typeof(LoggingClientWriteRepository));