gpt4 book ai didi

c# - Ninject - 请求范围已被处理

转载 作者:太空狗 更新时间:2023-10-29 23:23:39 26 4
gpt4 key购买 nike

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

我正在尝试将名为 IParentService 的服务注入(inject)到 Controller 中。 IParentService 依赖于通过 DependencyCreation 扩展创建的 ChildService(无硬引用)。

这两个服务都在本地事件代理实例上注册(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:\Projects\Ninject\ninject.extensions.namedscope\src\Ninject.Extensions.NamedScope\NamedScopeExtensionMethods.cs:118
Ninject.Extensions.NamedScope.NamedScopeExtensionMethods.GetScope(IContext context, String scopeParameterName) in c:\Projects\Ninject\ninject.extensions.namedscope\src\Ninject.Extensions.NamedScope\NamedScopeExtensionMethods.cs:126
Ninject.Extensions.NamedScope.<>c__DisplayClass1`1.<InNamedScope>b__0(IContext context) in c:\Projects\Ninject\ninject.extensions.namedscope\src\Ninject.Extensions.NamedScope\NamedScopeExtensionMethods.cs:40
Ninject.Planning.Bindings.BindingConfiguration.GetScope(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Bindings\BindingConfiguration.cs:119
Ninject.Planning.Bindings.Binding.GetScope(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Bindings\Binding.cs:224
Ninject.Activation.Context.GetScope() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:123
Ninject.Activation.Caching.Cache.TryGet(IContext context) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Caching\Cache.cs:110
Ninject.Activation.Context.Resolve() in c:\Projects\Ninject\ninject\src\Ninject\Activation\Context.cs:150
Ninject.<>c__DisplayClass10.<Resolve>b__c(IBinding binding) in c:\Projects\Ninject\ninject\src\Ninject\KernelBase.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:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:50
Ninject.Extensions.ContextPreservation.ContextPreservationExtensionMethods.ContextPreservingGet(IContext context, String name, IParameter[] parameters) in c:\Projects\Ninject\ninject.extensions.contextpreservation\src\Ninject.Extensions.ContextPreservation\ContextPreservationExtensionMethods.cs:56
Ninject.Extensions.bbvEventBroker.<>c__DisplayClass2`1.<RegisterOnEventBroker>b__0(IContext ctx, T instance) in c:\Projects\Ninject\ninject.extensions.bbveventbroker\src\Ninject.Extensions.bbvEventBroker\EventBrokerExtensionMethods.cs:45
Ninject.Planning.Bindings.<>c__DisplayClass29`1.<OnDeactivation>b__28(IContext context, Object instance) in c:\Projects\Ninject\ninject\src\Ninject\Planning\Bindings\BindingConfigurationBuilder.cs:513
Ninject.Activation.Strategies.<>c__DisplayClass4.<Deactivate>b__3(Action`2 action) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Strategies\BindingActionStrategy.cs:42
Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:32
Ninject.Activation.Strategies.BindingActionStrategy.Deactivate(IContext context, InstanceReference reference) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Strategies\BindingActionStrategy.cs:42
Ninject.Activation.<>c__DisplayClass6.<Deactivate>b__4(IActivationStrategy s) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Pipeline.cs:72
Ninject.Infrastructure.Language.ExtensionsForIEnumerableOfT.Map(IEnumerable`1 series, Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\Infrastructure\Language\ExtensionsForIEnumerableOfT.cs:32
Ninject.Activation.Pipeline.Deactivate(IContext context, InstanceReference reference) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Pipeline.cs:72
Ninject.Activation.Caching.Cache.Forget(CacheEntry entry) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Caching\Cache.cs:253
Ninject.Activation.Caching.Cache.Forget(IEnumerable`1 cacheEntries) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Caching\Cache.cs:242
Ninject.Activation.Caching.Cache.Clear(Object scope) in c:\Projects\Ninject\ninject\src\Ninject\Activation\Caching\Cache.cs:197
Ninject.Web.Common.<>c__DisplayClass2.<DeactivateInstancesForCurrentHttpRequest>b__1(IKernel kernel) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\OnePerRequestHttpModule.cs:74
Ninject.GlobalKernelRegistration.MapKernels(Action`1 action) in c:\Projects\Ninject\ninject\src\Ninject\GlobalKernelRegistration.cs:75
Ninject.Web.Common.OnePerRequestHttpModule.DeactivateInstancesForCurrentHttpRequest() in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\OnePerRequestHttpModule.cs:74
Ninject.Web.Common.OnePerRequestHttpModule.<Init>b__0(Object o, EventArgs e) in c:\Projects\Ninject\Ninject.Web.Common\src\Ninject.Web.Common\OnePerRequestHttpModule.cs:56
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +136
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +69

编辑 - 更多详细信息

错误是在对 RegisterOnEventBroker 的调用中设置的停用委托(delegate)中引发的,其中代码尝试注销在事件代理上注册的任何对象。它失败是因为事件代理范围已被释放,大概是因为父服务已被释放。据我所知,Ninject 只会为生命周期不是 Transient 范围的对象调用 OnDeactivation 委托(delegate),所以当父服务在 RequestScope 中注册时为什么这不起作用让我感到困惑。 transient 范围对于父服务来说是不够的,因为这个问题导致我遇到内存泄漏。

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

最佳答案

你必须先绑定(bind)IParentServiceParentService然后使用具体类型的自绑定(bind) kernel.Bind<ParentService>().ToSelf()定义对象范围和事件代理。

    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 将通过称为隐式自绑定(bind)的机制自动创建默认关联。像这样:

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

另一方面,隐式自绑定(bind)是在默认对象范围内生成的,即 Transient .这就是为什么您的代码不在 Request 中运行的原因范围。

有关详细信息,请参阅 here

编辑 2:

bbvEventBroker 中存在错误分机 Request导致 EventBroker 的作用域在处置在该 EventBroker 上注册的对象之前被处置。因此在OnDeactivation对象的方法没有可以调用其取消注册的 EventBroker 和 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中看到方法 NamedScope 在对象 ( ParentService) 的范围内定义,强制它在对象 (ParentService) 之前处理。

另一方面在OnDeactivation对象 ( ParentService ) 的 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)。通过这种方式,您可以确保事件代理的所有者将在他们的 child 之后被处置。

关于c# - Ninject - 请求范围已被处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16307915/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com