Search code examples
c#asp.netsimple-injector

The configuration is invalid Error for SimpleInjector


Error Message:

The configuration is invalid. Creating the instance for type UserController failed. The registered delegate for type UserController threw an exception. The registered delegate for type IApplicationDatabaseFactory returned null.

I have two databases, I am using Entity Framework.

Here is the link to the code: https://onedrive.live.com/redir?resid=738F28AF693709DC!388&authkey=!ALw3VMi6GEaiTZg&ithint=file%2c.zip

https://onedrive.live.com/redir?resid=738F28AF693709DC!391&authkey=!AJZ2fPbU7CBctYw&ithint=folder%2c

I need help in configuring the SimpleInjector.

There are two databases 1.SWT DB 2. Authorization DB
The SWT DB has RegionRepository Auth DB has UserRepository. They both have CommandHandlers in the constructors, which take the DBInstance. SimpleInjector has to be configured to pass the right instance of the DB to the repositories.

This is the Global.ascx code where the configuration is happening, need help in configuring the simpleInjector here in Application_Start()

 protected void Application_Start()
    {

        var container = new Container();

        var services = GlobalConfiguration.Configuration.Services;
        var controllerTypes = services.GetHttpControllerTypeResolver()
            .GetControllerTypes(services.GetAssembliesResolver());

        foreach (var controllerType in controllerTypes)
        {
            container.Register(controllerType);
        }

        container.RegisterAll<DbContext>(typeof(SWDMSEntities), typeof(TicketingDBEntities));

        container.Register<IAuthorizationDatabaseFactory>(() => new AuthorizationDatabaseFactory(new SWDMSEntities()), Lifestyle.Singleton);
        container.Register<ISWTDatabaseFactory>(() => new SWTDatabaseFactory(new TicketingDBEntities()), Lifestyle.Singleton);

        //container.RegisterAll<IApplicationDatabaseFactory>(typeof(AuthorizationDatabaseFactory), typeof(SWTDatabaseFactory));

        //registering 
        ////container.RegisterAll<IEntityCommand>(typeof(AddEntityCommand), typeof(DeleteEntityCommand));


        //// Register the command handler
        container.Register<ICommandHandler<AddEntityCommand>, AddEntityCommandHandler>();
        container.Register<ICommandHandler<UpdateEntityCommand>, UpdateEntityCommandHandler>();
        container.Register<ICommandHandler<DeleteEntityCommand>, DeleteEntityCommandHandler>();

        //// Go look in all assemblies and register all implementations
        //// of ICommandHandler<T> by their closed interface:

        ////container.RegisterManyForOpenGeneric(
        ////    typeof(ICommandHandler<>),
        ////    AppDomain.CurrentDomain.GetAssemblies());

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

        // Decorate each returned ICommandHandler<T> object with
        // a InfoLoggingCommandHandlerDecorator<T>.
        container.RegisterDecorator(
            typeof(ICommandHandler<>),
            typeof(InfoLoggingCommandHandlerDecorator<>));

        // Decorate each returned ICommandHandler<T> object with
        // a AuthorizationCommandHandlerDecorator<T>.
        container.RegisterDecorator(
            typeof(ICommandHandler<>),
            typeof(AuthorizationCommandHandlerDecorator<>));


        var lifestyle = new LifetimeScopeLifestyle();

        var Authdb = new InstanceProducer(typeof(IAuthorizationDatabaseFactory),
                lifestyle.CreateRegistration<IAuthorizationDatabaseFactory>(
                () => new AuthorizationDatabaseFactory(new SWDMSEntities()), container));

        var Appdb = new InstanceProducer(typeof(ISWTDatabaseFactory),
                lifestyle.CreateRegistration<ISWTDatabaseFactory>(
                () => new SWTDatabaseFactory(new TicketingDBEntities()), container));


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

            if (context.ImplementationType == typeof(IAuthorizationDatabaseFactory))
            {
                return container.GetInstance<IAuthorizationDatabaseFactory>();
                //return (IApplicationDatabaseFactory)Authdb.GetInstance();
            }
            else if (context.ImplementationType == typeof(ISWTDatabaseFactory))
            {
                return container.GetInstance<ISWTDatabaseFactory>();
                // return (IApplicationDatabaseFactory)Appdb.GetInstance();
            }
            else
            {
                return null;
            }
        });       


        //// Register your types, for instance:
        container.Register<IUserRepository, UserRepository>();
        container.Register<IRegionRepository, RegionRepository>();

        DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));

        // Verify the container configuration
        container.Verify();

        // Register the dependency resolver.
        GlobalConfiguration.Configuration.DependencyResolver =
            new SimpleInjectorWebApiDependencyResolver(container);
    }

Here are the Interfaces and classes

 public interface IApplicationDatabaseFactory :
    IDisposable
{
    DbContext GetContext();
}

public interface ISWTDatabaseFactory :
    IApplicationDatabaseFactory
{
}

 public interface IAuthorizationDatabaseFactory :
    IApplicationDatabaseFactory
{
}

 public abstract class ApplicationDatabaseFactoryBase :
    IApplicationDatabaseFactory
{
    private DbContext dataContext;
    private bool isDisposed;
    public ApplicationDatabaseFactoryBase(DbContext dBContext)
    {
        dBContext.Configuration.LazyLoadingEnabled = false;  ////Do not remove these lines as they are required
        dBContext.Configuration.ProxyCreationEnabled = false; ////Do not remove these lines as they are required
        this.dataContext = dBContext;
    }

    ~ApplicationDatabaseFactoryBase()
    {
        this.Dispose(false);
    }

    public DbContext GetContext()
    {
        return this.dataContext;
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void DisposeCore()
    {
        if (this.dataContext != null)
        {
            this.dataContext.Dispose();
        }
    }

    private void Dispose(bool disposing)
    {
        if (!this.isDisposed && disposing)
        {
            this.DisposeCore();
        }

        this.isDisposed = true;
    }
}

public class SWTDatabaseFactory :
    ApplicationDatabaseFactoryBase,
    ISWTDatabaseFactory
{
    public SWTDatabaseFactory( TicketingDBEntities  dBContext) :
        base((DbContext)dBContext)
    {
    }

    ~SWTDatabaseFactory()
    {
        this.Dispose();
    }
}

 public class AuthorizationDatabaseFactory : 
    ApplicationDatabaseFactoryBase,
    IAuthorizationDatabaseFactory
{       
    public AuthorizationDatabaseFactory(SWDMSEntities dbContext) :
        base((DbContext)dbContext)
    {
    }

    ~AuthorizationDatabaseFactory()
    {
        this.Dispose();
    }
}

public interface IRegionRepository :
    IRepository<Region>
{
}

 public class RegionRepository :
    RepositoryBase<Region>,
    IRegionRepository
{
    public RegionRepository(
        ISWTDatabaseFactory databaseFactory,
        ICommandHandler<AddEntityCommand> addEntityCommandHandler,
        ICommandHandler<UpdateEntityCommand> updateEntityCommandHandler,
        ICommandHandler<DeleteEntityCommand> deleteEntityCommandHandler)
        : base((IApplicationDatabaseFactory)databaseFactory, addEntityCommandHandler, updateEntityCommandHandler, deleteEntityCommandHandler)
    {
    }
}

 public interface IUserRepository :
   IRepository<Authorization_User>
{        
}

 public class UserRepository :
    RepositoryBase<Authorization_User>,
    IUserRepository
{
    public UserRepository(
        IAuthorizationDatabaseFactory databaseFactory,
        ICommandHandler<AddEntityCommand> addEntityCommandHandler,
        ICommandHandler<UpdateEntityCommand> updateEntityCommandHandler,
        ICommandHandler<DeleteEntityCommand> deleteEntityCommandHandler)
        : base(databaseFactory, addEntityCommandHandler, updateEntityCommandHandler, deleteEntityCommandHandler)
    {
    }
}

 public class AddEntityCommandHandler : 
    EntityCommandHandlerBase,
    ICommandHandler<AddEntityCommand>
{
    public AddEntityCommandHandler(IApplicationDatabaseFactory databaseFactory) :
        base(databaseFactory)
    {
    }
    public Execute(AddEntityCommand addEntityCommand)
    {
    }
}

Solution

  • You've coded null as a return type of IApplicationDatabaseFactory

    container.RegisterWithContext<IApplicationDatabaseFactory>(context =>
    {
        Type commandType = context.ServiceType.GetGenericArguments().Single();
    
        if (context.ImplementationType == typeof(IAuthorizationDatabaseFactory))
        {
            return container.GetInstance<IAuthorizationDatabaseFactory>();
        }
        else if (context.ImplementationType == typeof(ISWTDatabaseFactory))
        {
            return container.GetInstance<ISWTDatabaseFactory>();
        }
        else
        {
            // see here
            return null;
        }
    });
    

    I also don't think context.ImplementationType == typeof(IAuthorizationDatabaseFactory) will ever be true. Try something like this:

    container.RegisterWithContext<IApplicationDatabaseFactory>(context =>
    {
        if (typeof(IAuthorizationDatabaseFactory)
            .IsAssignableFrom(context.ImplementationType))
        {
            return container.GetInstance<IAuthorizationDatabaseFactory>();
        }
        else if (typeof(ISWTDatabaseFactory)
            .IsAssignableFrom(context.ImplementationType))
        {
            return container.GetInstance<ISWTDatabaseFactory>();
        }
        else
        {
            throw new InvalidOperationException();
        }
    }); 
    

    Ok, I can see what commandType was for now - you will want something like the code below which is attempting to return the IAuthorizationDatabaseFactory for an ICommandHandler<AddEntityCommand>

    container.RegisterWithContext<IApplicationDatabaseFactory>(context =>
    {
        Type commandType = context.ServiceType.GetGenericArguments().Single();
    
        if (commandType == typeof(AddEntityCommand))
        {
            return container.GetInstance<IAuthorizationDatabaseFactory>();
        }
        else
        {
            throw new InvalidOperationException();
        }
    });