请求范围已经处理完毕

我在MVC 3应用程序中使用Ninject和扩展EventBroker和DependencyCreation。 我已经安装并正在使用Ninject.MVC3软件包,因此也使用OnePerRequestModule

我试图将一个名为IParentService的服务注入到控制器中。 IParentService具有的依赖关系ChildService经由DependencyCreation扩展创建(没有硬参考)。

这两种服务都在本地事件代理实例( ParentService本地)上注册。

我希望IParentService可以根据请求作用域,并且我希望依赖和事件代理与IParentService ,但是,我得到一个ScopeDisposedException我究竟做错了什么?

一些代码:

服务定义:

public interface IParentService
{
}

public class ParentService : IParentService
{
    [EventPublication("topic://ParentService/MyEvent")]
    public event EventHandler<EventArgs> MyEvent;
}

public class ChildService
{
    [EventSubscription("topic://ParentService/MyEvent", typeof(bbv.Common.EventBroker.Handlers.Publisher))]
    public void OnMyEvent(object sender, EventArgs eventArgs)
    {            
    }
}

内核注册(NinjectWebCommon)

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IParentService>().To<ParentService>()
            .InRequestScope()
            .OwnsEventBroker("ParentServiceBroker")
            .RegisterOnEventBroker("ParentServiceBroker");

        kernel.DefineDependency<IParentService, ChildService>();
        kernel.Bind<ChildService>().ToSelf()
            .WhenInjectedInto<ParentService>()
            .InDependencyCreatorScope()
            .RegisterOnEventBroker("ParentServiceBroker");            
    }  

堆栈跟踪:

[ScopeDisposedException: The requested scope has already been disposed.]
   Ninject.Extensions.NamedScope.NamedScopeExtensionMethods.GetScope(IContext context, String scopeParameterName) in c:ProjectsNinjectninject.extensions.namedscopesrcNinject.Extensions.NamedScopeNamedScopeExtensionMethods.cs:118
   Ninject.Extensions.NamedScope.NamedScopeExtensionMethods.GetScope(IContext context, String scopeParameterName) in c:ProjectsNinjectninject.extensions.namedscopesrcNinject.Extensions.NamedScopeNamedScopeExtensionMethods.cs:126
   Ninject.Extensions.NamedScope.<>c__DisplayClass1`1.<InNamedScope>b__0(IContext context) in c:ProjectsNinjectninject.extensions.namedscopesrcNinject.Extensions.NamedScopeNamedScopeExtensionMethods.cs:40
   Ninject.Planning.Bindings.BindingConfiguration.GetScope(IContext context) in c:ProjectsNinjectninjectsrcNinjectPlanningBindingsBindingConfiguration.cs:119
   Ninject.Planning.Bindings.Binding.GetScope(IContext context) in c:ProjectsNinjectninjectsrcNinjectPlanningBindingsBinding.cs:224
   Ninject.Activation.Context.GetScope() in c:ProjectsNinjectninjectsrcNinjectActivationContext.cs:123
   Ninject.Activation.Caching.Cache.TryGet(IContext context) in c:ProjectsNinjectninjectsrcNinjectActivationCachingCache.cs:110
   Ninject.Activation.Context.Resolve() in c:ProjectsNinjectninjectsrcNinjectActivationContext.cs:150
   Ninject.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:ProjectsNinjectninjectsrcNinjectKernelBase.cs:386
   System.Linq.WhereSelectEnumerableIterator`2.MoveNext() +145
   System.Linq.<CastIterator>d__b1`1.MoveNext() +85
   System.Linq.Enumerable.Single(IEnumerable`1 source) +191
   Ninject.ResolutionExtensions.Get(IResolutionRoot root, String name, IParameter[] parameters) in c:ProjectsNinjectninjectsrcNinjectSyntaxResolutionExtensions.cs:50
   Ninject.Extensions.ContextPreservation.ContextPreservationExtensionMethods.ContextPreservingGet(IContext context, String name, IParameter[] parameters) in c:ProjectsNinjectninject.extensions.contextpreservationsrcNinject.Extensions.ContextPreservationContextPreservationExtensionMethods.cs:56
   Ninject.Extensions.bbvEventBroker.<>c__DisplayClass2`1.<RegisterOnEventBroker>b__0(IContext ctx, T instance) in c:ProjectsNinjectninject.extensions.bbveventbrokersrcNinject.Extensions.bbvEventBrokerEventBrokerExtensionMethods.cs:45
   Ninject.Planning.Bindings.<>c__DisplayClass29`1.<OnDeactivation>b__28(IContext context, Object instance) in c:ProjectsNinjectninjectsrcNinjectPlanningBindingsBindingConfigurationBuilder.cs:513
   Ninject.Activation.Strategies.<>c__DisplayClass4.<Deactivate>b__3(Action`2 action) in c:ProjectsNinjectninjectsrcNinjectActivationStrategiesBindingActionStrategy.cs:42
   Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:ProjectsNinjectninjectsrcNinjectInfrastructureLanguageExtensionsForIEnumerableOfT.cs:32
   Ninject.Activation.Strategies.BindingActionStrategy.Deactivate(IContext context, InstanceReference reference) in c:ProjectsNinjectninjectsrcNinjectActivationStrategiesBindingActionStrategy.cs:42
   Ninject.Activation.<>c__DisplayClass6.<Deactivate>b__4(IActivationStrategy s) in c:ProjectsNinjectninjectsrcNinjectActivationPipeline.cs:72
   Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:ProjectsNinjectninjectsrcNinjectInfrastructureLanguageExtensionsForIEnumerableOfT.cs:32
   Ninject.Activation.Pipeline.Deactivate(IContext context, InstanceReference reference) in c:ProjectsNinjectninjectsrcNinjectActivationPipeline.cs:72
   Ninject.Activation.Caching.Cache.Forget(CacheEntry entry) in c:ProjectsNinjectninjectsrcNinjectActivationCachingCache.cs:253
   Ninject.Activation.Caching.Cache.Forget(IEnumerable`1 cacheEntries) in c:ProjectsNinjectninjectsrcNinjectActivationCachingCache.cs:242
   Ninject.Activation.Caching.Cache.Clear(Object scope) in c:ProjectsNinjectninjectsrcNinjectActivationCachingCache.cs:197
   Ninject.Web.Common.<>c__DisplayClass2.<DeactivateInstancesForCurrentHttpRequest>b__1(IKernel kernel) in c:ProjectsNinjectNinject.Web.CommonsrcNinject.Web.CommonOnePerRequestHttpModule.cs:74
   Ninject.GlobalKernelRegistration.MapKernels(Action`1 action) in c:ProjectsNinjectninjectsrcNinjectGlobalKernelRegistration.cs:75
   Ninject.Web.Common.OnePerRequestHttpModule.DeactivateInstancesForCurrentHttpRequest() in c:ProjectsNinjectNinject.Web.CommonsrcNinject.Web.CommonOnePerRequestHttpModule.cs:74
   Ninject.Web.Common.OnePerRequestHttpModule.<Init>b__0(Object o, EventArgs e) in c:ProjectsNinjectNinject.Web.CommonsrcNinject.Web.CommonOnePerRequestHttpModule.cs:56
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

编辑 - 更多细节

该错误将在调用RegisterOnEventBroker设置的停用委托中引发,代码将尝试取消注册在事件代理上注册的任何对象。 它失败了,因为事件代理范围已被处置,可能是因为父服务已被处置。 据我所知,Ninject只会调用OnDeactivation委托来处理除Transient作用域以外的生命期的对象,那么为什么在RequestScope注册父服务时会RequestScope 。 由于此问题,我正在经历内存泄漏,所以父服务的暂态范围不足。

我开始怀疑这是否是EventBroker扩展中的一个错误。


您必须先将IParentService绑定到ParentService然后使用具体类型kernel.Bind<ParentService>().ToSelf()自绑定kernel.Bind<ParentService>().ToSelf()来定义Object范围和事件代理。

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IParentService>().To<ParentService>();


        kernel.Bind<ParentService>().ToSelf()
       .InRequestScope()
       .OwnsEventBroker("ParentServiceBroker")
       .RegisterOnEventBroker("ParentServiceBroker");

        kernel.DefineDependency<IParentService, ChildService>();
        kernel.Bind<ChildService>().ToSelf()
            .WhenInjectedInto<ParentService>()
            .InDependencyCreatorScope()
            .RegisterOnEventBroker("ParentServiceBroker"); 
    }    

编辑:如果您要解析的类型是具体类型(如上面的ParentService),Ninject会通过一种称为隐式自绑定的机制自动创建默认关联。 喜欢这个:

 kernel.Bind<ParentService>().ToSelf();

另一方面,隐式自我绑定在默认的Object Transient 。 这就是为什么你的代码不能在Request范围内运行。

欲了解更多信息,请看这里

编辑2:

Request范围内的bbvEventBroker扩展中存在一个错误,这会导致EventBroker在处理在该EventBroker上注册的对象之前处置。 因此,在对象的OnDeactivation方法中,没有可以调用它的Unregister和ScopeDisposedException抛出的ScopeDisposedException

    public static IBindingOnSyntax<T> OwnsEventBroker<T>(this IBindingOnSyntax<T> syntax, string eventBrokerName)
    {
        string namedScopeName = "EventBrokerScope" + eventBrokerName;
        syntax.DefinesNamedScope(namedScopeName);
        syntax.Kernel.Bind<IEventBroker>().To<EventBroker>().InNamedScope(namedScopeName).Named(eventBrokerName);
        syntax.Kernel.Bind<IEventBroker>().ToMethod(ctx => ctx.ContextPreservingGet<IEventBroker>(eventBrokerName)).WhenTargetNamed(eventBrokerName);
        return syntax;
    }

您可以在OwnsEventBroker方法中看到, OwnsEventBroker在对象( ParentService )的作用域( ParentService )中定义了强制它在对象( ParentService )之前处理的方法。

另一方面,在对象的OnDeactivationParentService )中,需要事先放置的EventBroker。

    public static IBindingOnSyntax<T> RegisterOnEventBroker<T>(
        this IBindingOnSyntax<T> syntax, string eventBrokerName)
    {
        return
            syntax.OnActivation((ctx, instance) => ctx.ContextPreservingGet<IEventBroker>(eventBrokerName).Register(instance))
                  .OnDeactivation((ctx, instance) => ctx.ContextPreservingGet<IEventBroker>(eventBrokerName).Unregister(instance));
    }

EventBrokerExtensionMethods.cs

解决方案是使用NamedScope创建对象树。 在定义父Request范围,而它定义NamedScope为其子女(发布/订阅),并拥有该事件代理( OwnsEventBroker )。 然后在父指定的范围内定义发布者( ChildService1 )和订阅者( ChildService2 )。 通过这种方式,您可以确保活动经纪人的所有者在他们的孩子后被处置。


Ninject内核当前停用处于对象范围内的对象,然后停用对象本身。

改变顺序似乎解决了这个问题。 虽然在推动这个变化之前,我必须检查这可能对其他情况有什么副作用。

链接地址: http://www.djcxy.com/p/66273.html

上一篇: Request scope has already been disposed

下一篇: ninject and enterprise library service locator dependant assemblies