2013-04-30 11 views
5

私はMVC 3アプリケーションでNinjectと拡張EventBrokerとDependencyCreationを使用しています。私はインストールして、Ninject.MVC3パッケージを使用しているので、OnePerRequestModuleです。Ninject - 要求スコープは既に破棄されています

IParentServiceというサービスをコントローラに挿入しようとしています。 IParentServiceは、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:\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 

EDIT - 詳細

エラーがコードは、イベント・ブローカに登録されたオブジェクトの登録を解除しようとRegisterOnEventBrokerへのコールに設定されている不活性化デリゲート内でスローされます。イベントブローカのスコープが破棄されたため、親サービスが破棄されたためと考えられます。私が知っている限り、Ninjectは、Transientスコープ以外の生存期間を持つオブジェクトのOnDeactivation代理人のみを呼び出すため、親サービスがRequestScopeに登録されていると、なぜこれが動作しないのですか?この問題のためにメモリリークが発生しているため、一時的なスコープでは親サービスには不十分です。

これはEventBroker拡張のバグかどうか疑問に思っています。

答えて

2

IParentServiceParentServiceにバインドし、コンクリートタイプ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は自動的に暗黙の自己結合と呼ばれる機構を介してデフォルトの関連付けを作成します。このよう :一方の暗黙的な自己バインディングに

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

Transientあるデフォルトのオブジェクトスコープ内で発生しています。このため、コードはRequestスコープで実行されません。詳細については

は編集2 here

を参照してください。

イベント・ブローカはそのイベント・ブローカに登録したオブジェクトを廃棄する前に配置された原因Request範囲内bbvEventBroker拡張子にバグがあります。したがってオブジェクトのOnDeactivationメソッドでは、Unregisterを呼び出すことができる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; 
    } 

あなたがオブジェクト(ParentService)の前に配置することを強制オブジェクト(ParentService)の範囲で定義NamedScope OwnsEventBroker方法で見ることができます。

一方、オブジェクト(ParentService)のOnDeactivationには、先に配置した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スコープに親を定義し、子(Publisher/Subscriber)にはNamedScopeを定義し、イベントブローカー(OwnsEventBroker)を所有します。次に、発行者(ChildService1)を定義し、名前付きスコープ内のサブスクライバ(ChildService2)を親によって定義されたものとします。このようにして、イベントブローカーの所有者が子供の後に処分されるようにすることができます。

+0

感謝Kambiz、エラーを解決します。私はそれをやっているやり方や、なぜこのようにする必要があるのか​​、何が間違っているのかをもう少し詳しく説明できますか? – nukefusion

+0

@nukefusion私は答えを更新しました –

+0

私はこれを2倍にしましたが、私のテストでは具体的なタイプではなくIParentServiceを注入しています。これは私の問題を修正するように見えましたが、実際には2番目の '自己'バインディングの代わりに最初のバインディングを使用していました。あなたのコードを使用して 'ParentService'インスタンスを挿入すると、同じ例外が発生します。 – nukefusion

2

現在、Ninjectコアはオブジェクトのスコープ内にあるオブジェクトを非アクティブ化してから、オブジェクト自体を非アクティブ化します。

注文を変更すると問題が解決したようです。この変更を行う前に、これが他の状況に対してどのような副作用を持っているかを確認する必要があります。

+0

このRemoを調べていただきありがとうございます。私はそれを追跡することができますこれのためのオープンな問題はありますか? – nukefusion

関連する問題