Ninject and packaging service, infrastructure and

2019-09-16 15:11发布

问题:

I am a HUGE fan of ninject. To date however I have only used it for single application injections. I currently want to package up my services infrastructure and data layers that I have created.

Basically my infrastructure layer has the contracts for creating the stored procedure Dao's that my services layer needs to pass to the data layer. The data layer does the SP call with the parameters added to the DAO and returns a dataset. All of this works excellently.

I use constructor based dependency injection on all three of them and I would like to prepackage the IOC with them. That way when I use them in another application I do not have to rewire the dependency injection for the classes in the dll.

Every time I have currently used ninject, I wire up a ninject webcommon that does the entire application top to bottom.

namespace MyApp.App_Start
{
    using System;
    using System.Web;

    using Microsoft.Web.Infrastructure.DynamicModuleHelper;

    using Ninject;
    using Ninject.Web.Common;

    public static class NinjectWebCommon 
    {
        private static readonly Bootstrapper bootstrapper = new Bootstrapper();

        /// <summary>
        /// Starts the application
        /// </summary>
        public static void Start() 
        {
            DynamicModuleUtility
                .RegisterModule(typeof(OnePerRequestHttpModule));

            DynamicModuleUtility
                .RegisterModule(typeof(NinjectHttpModule));

            bootstrapper.Initialize(CreateKernel);
        }

        /// <summary>
        /// Stops the application.
        /// </summary>
        public static void Stop()
        {
            bootstrapper.ShutDown();
        }

        /// <summary>
        /// Creates the kernel that will manage your application.
        /// </summary>
        /// <returns>The created kernel.</returns>
        private static IKernel CreateKernel()
        {
            var kernel = new StandardKernel();
            AutoMapper.AutoMapperConfigurator.Configure();

            try
            {
                kernel.Bind<Func<IKernel>>()
                    .ToMethod(ctx => () => new Bootstrapper().Kernel);
                kernel.Bind<IHttpModule>()
                    .To<HttpApplicationInitializationHttpModule>();

                RegisterServices(kernel);
                return kernel;
            }
            catch
            {
                kernel.Dispose();
                throw;
            }
        }

        /// <summary>
        /// Load your modules or register your services here!
        /// </summary>
        /// <param name="kernel">The kernel.</param>
        private static void RegisterServices(IKernel kernel)
        {
            kernel.Bind<IQuerySelector>().To<QuerySelector>();
            kernel.Bind<IQueryExecutor>().To<QueryExecutor>();
            kernel.Bind<ISqlParameterPopulationService>()
                .To<SqlParameterPopulationService>();
        }        
    }

I would like one IOC in my prepackaged Dll's that the developer doesn't access and then the user can have her/his own IOC that they would add all of their injections to.

回答1:

It's doable.

I usually create a separate "CompostionRoot" project, which itself references my central interface and concrete business/service/data layers, etc, then add Ninject to it, add a reference to this project to my MVC/WebAPI project, then finally pass the kernel from Ninject.Web.Common in the RegisterServices function

i.e

using CompositionRoot; 
...
...

private static void RegisterServices(IKernel kernel)
        {
            var cr = new MyExternalComposer(kernel);
            cr.DoBindings();
        }  

Now this might not be considered "best practice" but what I like about that approach is that I have no dependencies at all on concrete business/service/data layer implementations from my MVC project - everything can be done by interface by just referencing my Interfaces project from the MVC project, plus the project can be re-used in other solutions. It's just an extra layer of indirection I suppose and I haven't come across any drawbacks from doing it this way so far...

Hope that helps.