Keep Alive settings when subscribing to Events

Topics: Enterprise Library Core, Exception Handling Application Block, General discussion, Policy Injection Application Block
Mar 25, 2010 at 12:05 PM

Hi,
Im subscribing to some events in a View Model class such:

        private void Subscibe(IEventAggregator eventAggregator)
        {
            // Subscribe to logged out event (from menu or button or what evre
            eventAggregator.GetEvent<EventCommand>().Subscribe(
                   OnCommandEvent,            // the function that implements the response
                   ThreadOption.UIThread,     // invoke subscription on the UI Thread
                    true,                                // false KeepAlive means weak fn references such that this object will be GCed as soon as not anymore in use
                                                           // However this caused an exception, so I put it to true and the ScreenFactoryMap is responsible for unsubscribing
                                                           // to allow the instance to be GCed

                   null                                   // Fn to filter events so only hear pertinent events
                  );
        }

Notice the red section in my call. I use a screenfactory to instantiate the view model class such (notice again the red sectoin):

        private void CreateAndShowMapView() {
          if (m_viewModel != null)
              return; // race guard; superfluous?
          CreateMapView();
          ShowMapView();
        }

        private void CreateMapView() {
          m_view = m_container.Resolve<ViewMap>();
          m_viewModel = m_container.Resolve<VMMap>();
          m_view.DataContext = m_viewModel;
        }

        private void ShowMapView() {
          m_regionManager.AddToRegion(RegionNames.Map, m_view);
        }

I was going to subscribe to events in the VM class by setting keepAlive = false to avoid having to call Unsubscribe() when the view is closed (I'm opening the view and closing as user requests). Setting keepAlive to true and not calling Unsubscribe() will cause memory leak as the EventAggregator keeps a strong link to the VM instance after it is no more in use.

If I set the keepAlive parameter to false I get an ActivationException telling "Activation error occured while trying to get instance of type VMMap, key """" when calling eventAggregator.GetEvent<EventCommand>().Subscribe(...) as detailed above.
Why is that happening for keepAlive = false?

The exception details are:
{Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type VMMap, key "" ---> Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "C2Net.Modules.Map.VMMap", name = "". Exception message is: The current build operation (build key Build Key[C2Net.Modules.Map.VMMap, null]) failed: C2Net.Modules.Map.VMMap.OnLoggedIn(C2Net.Modules.Infrastructure.EventAggregation.EventLoggedIn) (Strategy type BuildPlanStrategy, index 3) ---> Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[C2Net.Modules.Map.VMMap, null]) failed: C2Net.Modules.Map.VMMap.OnLoggedIn(C2Net.Modules.Infrastructure.EventAggregation.EventLoggedIn) (Strategy type BuildPlanStrategy, index 3) ---> System.MethodAccessException: C2Net.Modules.Map.VMMap.OnLoggedIn(C2Net.Modules.Infrastructure.EventAggregation.EventLoggedIn)
   at System.Delegate.BindToMethodInfo(Object target, RuntimeMethodHandle method, RuntimeTypeHandle methodType, DelegateBindingFlags flags)
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
   at Microsoft.Practices.Composite.Events.DelegateReference.TryGetDelegate()
   at Microsoft.Practices.Composite.Events.DelegateReference.get_Target()
   at Microsoft.Practices.Composite.Events.EventSubscription`1..ctor(IDelegateReference actionReference, IDelegateReference filterReference)
   at Microsoft.Practices.Composite.Presentation.Events.DispatcherEventSubscription`1..ctor(IDelegateReference actionReference, IDelegateReference filterReference, IDispatcherFacade dispatcher)
   at Microsoft.Practices.Composite.Presentation.Events.CompositePresentationEvent`1.Subscribe(Action`1 action, ThreadOption threadOption, Boolean keepSubscriberReferenceAlive, Predicate`1 filter)
   at C2Net.Modules.Map.VMMap.Subscibe(IEventAggregator eventAggregator)
   at C2Net.Modules.Map.VMMap..ctor(IMapRepository repository, IEventAggregator eventAggregator)
   at BuildUp_C2Net.Modules.Map.VMMap(IBuilderContext )
   at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
   at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
   at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
   at Microsoft.Practices.ObjectBuilder2.Builder.BuildUp(IReadWriteLocator locator, ILifetimeContainer lifetime, IPolicyList policies, IStrategyChain strategies, Object buildKey, Object existing)
   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name)
   at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name)
   at Microsoft.Practices.Composite.UnityExtensions.UnityServiceLocatorAdapter.DoGetInstance(Type serviceType, String key)
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService]()
   at C2Net.Modules.Map.ScreenFactoryMap.CreateMapView()
   at C2Net.Modules.Map.ScreenFactoryMap.CreateAndShowMapView()
   at C2Net.Modules.Map.ScreenFactoryMap.OnCommandEvent(EventCommand msg)}

Inner exceptoin is:
{Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "C2Net.Modules.Map.VMMap", name = "". Exception message is: The current build operation (build key Build Key[C2Net.Modules.Map.VMMap, null]) failed: C2Net.Modules.Map.VMMap.OnLoggedIn(C2Net.Modules.Infrastructure.EventAggregation.EventLoggedIn) (Strategy type BuildPlanStrategy, index 3) ---> Microsoft.Practices.ObjectBuilder2.BuildFailedException: The current build operation (build key Build Key[C2Net.Modules.Map.VMMap, null]) failed: C2Net.Modules.Map.VMMap.OnLoggedIn(C2Net.Modules.Infrastructure.EventAggregation.EventLoggedIn) (Strategy type BuildPlanStrategy, index 3) ---> System.MethodAccessException: C2Net.Modules.Map.VMMap.OnLoggedIn(C2Net.Modules.Infrastructure.EventAggregation.EventLoggedIn)
   at System.Delegate.BindToMethodInfo(Object target, RuntimeMethodHandle method, RuntimeTypeHandle methodType, DelegateBindingFlags flags)
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure)
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method)
   at Microsoft.Practices.Composite.Events.DelegateReference.TryGetDelegate()
   at Microsoft.Practices.Composite.Events.DelegateReference.get_Target()
   at Microsoft.Practices.Composite.Events.EventSubscription`1..ctor(IDelegateReference actionReference, IDelegateReference filterReference)
   at Microsoft.Practices.Composite.Presentation.Events.DispatcherEventSubscription`1..ctor(IDelegateReference actionReference, IDelegateReference filterReference, IDispatcherFacade dispatcher)
   at Microsoft.Practices.Composite.Presentation.Events.CompositePresentationEvent`1.Subscribe(Action`1 action, ThreadOption threadOption, Boolean keepSubscriberReferenceAlive, Predicate`1 filter)
   at C2Net.Modules.Map.VMMap.Subscibe(IEventAggregator eventAggregator)
   at C2Net.Modules.Map.VMMap..ctor(IMapRepository repository, IEventAggregator eventAggregator)
   at BuildUp_C2Net.Modules.Map.VMMap(IBuilderContext )
   at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
   at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
   at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
   at Microsoft.Practices.ObjectBuilder2.Builder.BuildUp(IReadWriteLocator locator, ILifetimeContainer lifetime, IPolicyList policies, IStrategyChain strategies, Object buildKey, Object existing)
   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
   --- End of inner exception stack trace ---
   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name)
   at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name)
   at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name)
   at Microsoft.Practices.Composite.UnityExtensions.UnityServiceLocatorAdapter.DoGetInstance(Type serviceType, String key)
   at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key)}

Mar 26, 2010 at 10:34 AM

Try posting your problem here http://unity.codeplex.com/Thread/List.aspx,  you might get your answer there. :)