Очистить все регионы / виды на Prism 4 (Silverlight) Выйти

В моем приложении silverlight есть 2 области, использующие вид основной оболочки Prism 4 и unity, область аутентификации и область без аутентификации, а также пункт меню.

В аутентифицированной области существует намного больше субрегионов, в зависимости от введенного в нее представления.

При загрузке приложения мне будет представлен экран входа в систему «Неаутентифицированный регион», при входе в систему я буду представлен в Аутентифицированном регионе.

Когда я нажимаю кнопку выхода в меню, мне снова будет представлен вид входа в систему.

Но когда я вхожу в систему во второй раз, мое существующее представление, загруженное в аутентифицированной области, все еще там.

Я попробовал следующий код при выходе из системы, чтобы удалить все представления из этого региона, но представления, полученные из контейнера, по-прежнему являются существующим представлением.

        var regions = this.RegionManager.Regions;
        foreach (var region in regions)
        {
            if (region.Name == this.AuthenticatedRegionName)
            {                    
                var views = region.Views;

                foreach(var view in views)
                {
                    region.Remove(view);                        
                }                    
            }
        }

Я действительно получаю ошибку не найденного ключа региона, когда по какой-то причине вызываю запрос навигации, но я думаю, что основная проблема связана с контейнером.

Как я могу указать единству, что все представления будут размещены?


person Joshscorp    schedule 21.02.2011    source источник
comment
Вы случайно определили данное представление как ContainerControlledLifetime? Region.Remove должно быть достаточно для удаления View из данного региона. Вызов Resolve в контейнере для данного типа представления должен предоставить новый экземпляр, если у вас нет диспетчера времени жизни.   -  person Aaron McIver    schedule 21.02.2011
comment
Спасибо за ответ, я думаю, что это имеет смысл, да, некоторые из моих экранов - containerControlledLifetime (одиночные) ... как я могу сбросить / очистить диспетчер времени жизни?   -  person Joshscorp    schedule 21.02.2011
comment
Добавлен ответ, касающийся вашей проблемы; предлагает другой подход   -  person Aaron McIver    schedule 21.02.2011


Ответы (2)


Поскольку вы используете ContainerControlledLifetimeManager для представления, представление будет разрешено в один и тот же экземпляр на время существования IUnityContainer. Удаление представления из области никоим образом не удаляет его из IUnityContainer, поскольку IUnityContainer содержит сильную ссылку на представление.

Лучший подход - не заставлять ваши представления вести себя как синглтоны. Если вы хотите использовать одноэлементное поведение, перенесите это поведение либо в службу, либо в модель представления, которая может оставаться в течение всего срока службы IUnityContainer без каких-либо негативных последствий.

Представление не должно вести себя с учетом состояния; он должен оставаться без состояния, и поэтому следует избегать принуждения вашего View к работе как Singleton.

Если вы уверены, что хотите, чтобы в вашем представлении было одноэлементное поведение, вы можете использовать ExternallyControlledLifetimeManager, который будет содержать слабую ссылку на представление. После этого View будет обработан сборщиком мусора после того, как будут удалены все сильные ссылки на него.

person Aaron McIver    schedule 21.02.2011

Я решил это, пройдя цикл через UnityContainer.Registration и проверив LifetimeManagerType для каждой регистрации, если они имеют ContainerControlledLifetimeManager и MappedToType, равные моему типу модели базового представления, я создаю для него новый экземпляр, так что устанавливаю его на установленное значение на ВЫХОД.

var registrations = this.UnityContainer.Registrations;
            if (registrations != null)
            {
                foreach (var registration in registrations)
                {
                    if (registration.LifetimeManagerType != null &&
                        registration.LifetimeManagerType ==               typeof(ContainerControlledLifetimeManager) &&
                        registration.MappedToType.FullName.Equals("Main.ViewModelBase"))
                    {
                        var objectType = registration.LifetimeManager.GetValue().GetType();
                        var newInstance = Activator.CreateInstance(objectType, new object[]{this.UnityContainer});

                        registration.LifetimeManager.SetValue(newInstance);                           
                    }
                }
            }

Не элегантно, но пока работает, ура

person Joshscorp    schedule 21.02.2011
comment
Должно быть, у View были сильные ссылки; возможно через события - person Aaron McIver; 22.02.2011