Looking for a Ninject scope that behaves like InRequestScope

前端 未结 2 689
庸人自扰
庸人自扰 2020-11-28 16:32

On my service layer I have injected an UnitOfWork and 2 repositories in the constructor. The Unit of Work and repository have an instance of a DbContext

2条回答
  •  甜味超标
    2020-11-28 17:10

    As discussed in the other answer, InCallScope is not a good approach to solving this problem.

    For now I'm dumping some code that works against the latest NuGet Unstable / Include PreRelease / Instal-Package -Pre editions of Ninject.Web.Common without a clear explanation. I will translate this to an article in the Ninject.Extensions.NamedScope wiki at some stagehave started to write a walkthrough of this technique in the Ninject.Extensions.NamedScope wiki's CreateNamedScope/GetScope article.

    Possibly some bits will become Pull Request(s) at some stage too (Hat tip to @Remo Gloor who supplied me the outline code). The associated tests and learning tests are in this gist for now), pending packaging in a proper released format TBD.

    The exec summary is you Load the Module below into your Kernel and use .InRequestScope() on everything you want created / Disposed per handler invocation and then feed requests through via IHandlerComposer.ComposeCallDispose.

    If you use the following Module:

    public class Module : NinjectModule
    {
        public override void Load()
        {
            Bind().To();
    
            // Wire it up so InRequestScope will work for Handler scopes
            Bind().To();
            NinjectRequestHandlerScopeFactory.NinjectHttpApplicationPlugin.RegisterIn( Kernel );
        }
    }
    

    Which wires in a Factory[1] and NinjectHttpApplicationPlugin that exposes:

    public interface INinjectRequestHandlerScopeFactory
    {
        NamedScope CreateRequestHandlerScope();
    }
    

    Then you can use this Composer to Run a Request InRequestScope():

    public interface IHandlerComposer
    {
        void ComposeCallDispose( Type type, Action callback );
    }
    
    
    

    Implemented as:

    class NinjectRequestScopedHandlerComposer : IHandlerComposer
    {
        readonly INinjectRequestHandlerScopeFactory _requestHandlerScopeFactory;
    
        public NinjectRequestScopedHandlerComposer( INinjectRequestHandlerScopeFactory requestHandlerScopeFactory )
        {
            _requestHandlerScopeFactory = requestHandlerScopeFactory;
        }
    
        void IHandlerComposer.ComposeCallDispose( Type handlerType, Action callback )
        {
            using ( var resolutionRoot = _requestHandlerScopeFactory.CreateRequestHandlerScope() )
                foreach ( object handler in resolutionRoot.GetAll( handlerType ) )
                    callback( handler );
        }
    }
    
    
    

    The Ninject Infrastructure stuff:

    class NinjectRequestHandlerScopeFactory : INinjectRequestHandlerScopeFactory
    {
        internal const string ScopeName = "Handler";
    
        readonly IKernel _kernel;
    
        public NinjectRequestHandlerScopeFactory( IKernel kernel )
        {
            _kernel = kernel;
        }
    
        NamedScope INinjectRequestHandlerScopeFactory.CreateRequestHandlerScope()
        {
            return _kernel.CreateNamedScope( ScopeName );
        }
    
        /// 
        /// When plugged in as a Ninject Kernel Component via RegisterIn(IKernel), makes the Named Scope generated during IHandlerFactory.RunAndDispose available for use via the Ninject.Web.Common's .InRequestScope() Binding extension.
        /// 
        public class NinjectHttpApplicationPlugin : NinjectComponent, INinjectHttpApplicationPlugin
        {
            readonly IKernel kernel;
    
            public static void RegisterIn( IKernel kernel )
            {
                kernel.Components.Add();
            }
    
            public NinjectHttpApplicationPlugin( IKernel kernel )
            {
                this.kernel = kernel;
            }
    
            object INinjectHttpApplicationPlugin.GetRequestScope( IContext context )
            {
                // TODO PR for TrgGetScope
                try
                {
                    return NamedScopeExtensionMethods.GetScope( context, ScopeName );
                }
                catch ( UnknownScopeException )
                {
                    return null;
                }
            }
    
            void INinjectHttpApplicationPlugin.Start()
            {
            }
    
            void INinjectHttpApplicationPlugin.Stop()
            {
            }
        }
    }
    

    提交回复
    热议问题