2013-04-30 17 views
5

मैं Ninject का उपयोग कर रहा हूं और एमवीसी 3 एप्लिकेशन में एक्सटेंशन इवेंट ब्रोकर और निर्भरता क्रिएशन का उपयोग कर रहा हूं। मैंने स्थापित किया है और Ninject.MVC3 पैकेज का उपयोग कर रहा हूं और इसलिए OnePerRequestModule का उपयोग कर रहा हूं।निंजा - अनुरोध का दायरा पहले ही डिस्पोजेड किया गया है

मैं एक सेवा इंजेक्ट करने का प्रयास कर रहा हूं, जिसे नियंत्रक में IParentService कहा जाता है। IParentService पर निर्भरता ChildService पर निर्भरता निर्भरता विस्तार (कोई कठोर संदर्भ) के माध्यम से बनाई गई है।

दोनों सेवाएं स्थानीय ईवेंट ब्रोकर इंस्टेंस (ParentService पर स्थानीय) पर पंजीकृत हैं।

मैं चाहता हूँ IParentService अनुरोध के अनुसार scoped जा करने के लिए और मैं निर्भरता और घटना दलाल 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, जहां कोड घटना दलाल पर पंजीकृत किसी भी वस्तुओं का पंजीकरण रद्द करने का प्रयास करने के लिए कॉल में सेट है अंदर फेंक दिया है। यह विफल रहता है क्योंकि इवेंट ब्रोकर स्कोप का निपटारा किया गया है, संभवतः क्योंकि मूल सेवा का निपटारा किया गया है। जहां तक ​​मुझे पता है, निनजेक्ट केवल क्षणिक दायरे के अलावा अन्य समय के साथ ऑब्जेक्टिवेशन प्रतिनिधियों को कॉल करेगा, इसलिए यह क्यों काम नहीं करता है जब पेरिस सेवा RequestScope में पंजीकृत है, मुझे भ्रमित करती है। क्षणिक सेवा माता-पिता सेवा के लिए पर्याप्त नहीं है क्योंकि मुझे इस समस्या के कारण स्मृति रिसाव का सामना करना पड़ रहा है।

मुझे आश्चर्य है कि यह EventBroker एक्सटेंशन में एक बग है या नहीं।

उत्तर

2

आपको पहले IParentService से ParentService बांधना होगा, फिर ऑब्जेक्ट स्कोप और ईवेंट ब्रोकर को परिभाषित करने के लिए कंक्रीट प्रकार 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 गुंजाइश में नहीं चलता है।

अधिक जानकारी के लिए देख here

संपादित 2:

वहाँ Request गुंजाइश जिसके कारण EventBroker वस्तु जो कि EventBroker पर पंजीकृत करता है के निपटान से पहले निपटारा किया गया था में bbvEventBroker विस्तार में एक बग है। इसलिए OnDeactivation ऑब्जेक्ट की विधि में कोई इवेंट ब्रोकर नहीं है जिसकी अनियंत्रक को बुलाया जा सकता है और 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 विधि में देख वस्तु (ParentService) जो यह वस्तु (ParentService) से पहले निपटाने के लिए लागू के दायरे में परिभाषित NamedScope कर सकते हैं।

दूसरी ओर ऑब्जेक्ट (ParentService) के OnDeactivation में इवेंट ब्रोकर की आवश्यकता है जो पहले निपटान किया गया था।

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) परिभाषित किया गया था। इस तरह आप यह सुनिश्चित कर सकते हैं कि ईवेंट ब्रोकर के मालिक को उनके बच्चे के बाद निपटान किया जाएगा।

+0

धन्यवाद कंबिज, जो त्रुटि को हल करता है। क्या आप इस तरीके से गलत तरीके से विस्तार कर सकते हैं कि मैं इसे किस तरह से कर रहा था और इसे इस तरह क्यों किया जाना चाहिए? – nukefusion

+0

@nukefusion मैंने जवाब को अद्यतन किया है –

+0

मैंने इसे दोगुना कर दिया है लेकिन मेरे परीक्षण में मैं आईपीआरएस सेवा को इंजेक्शन कर रहा हूं, ठोस प्रकार नहीं। यह मेरी समस्या को ठीक करने के लिए दिखाई दिया लेकिन वास्तव में यह केवल दूसरे 'स्वयं' बाध्यकारी के बजाय अपने पहले बाध्यकारी का उपयोग कर रहा था। यदि मैं आपके कोड का उपयोग करता हूं और 'पेरेंट सेवा' उदाहरण इंजेक्ट करता हूं तो मुझे एक ही अपवाद मिलता है। – nukefusion

2

निनजाल कोर वर्तमान में ऑब्जेक्ट को निष्क्रिय करने से पहले ऑब्जेक्ट के दायरे में मौजूद वस्तुओं को निष्क्रिय करता है।

आदेश बदलना उस समस्या को ठीक करने लगता है। हालांकि उस परिवर्तन को धक्का देने से पहले मुझे यह जांचना होगा कि अन्य परिस्थितियों के लिए इसका क्या दुष्प्रभाव हो सकता है।

+0

इस रेमो को देखने के लिए धन्यवाद। क्या इसके लिए कोई खुली समस्या है इसलिए मैं इसे ट्रैक कर सकता हूं? – nukefusion

संबंधित मुद्दे