Как обрабатывать динамический экземпляр (Window) с контейнером SimpleIoc - PullRequest
0 голосов
/ 28 ноября 2018

Я новичок в MVVM и IoC.Я использую ViewModel-первый подход для этого проекта.Моя организация сборок проекта выглядит следующим образом:

View (имеет ссылку на ViewModel)
ViewModel (имеет ссылку на Model)
Model

Поначалу работал нормально, пока мне не нужно представление Login.Login запускать при запуске программы.При успешном входе в систему будет отображаться MainWindow, а Login должен сам закрыться.Обратное можно сделать с помощью LogoutCommand из MainWindow.

Основным препятствием, с которым я сталкиваюсь, является создание View (Окна) для данного типа ViewModel, в то время как ViewModel не знает о View.В поисках ответа я нашел:

  1. Шаблон Посредник / Посланник.Что мне показалось очень удобным, я использовал этот шаблон для отображения диалога MessageBox.Но только для этой цели мне неудобно использовать этот шаблон для обработки объектов.
  2. Внедрение зависимостей.Новая концепция для меня.Но я вижу реальную выгоду отделения знаний конструктора сервиса от потребительского класса.Поэтому я попробовал MVVM-Light SimpleIoc для начала, введя View экземпляр в ViewModel конструктор в качестве интерфейса и продолжил регистрировать их на ViewModelLocator
SimpleIoc.Default.Register<IMainWindowView, MainWindow>();  
SimpleIoc.Default.Register<ILoginView, Login>();  
SimpleIoc.Default.Register<LoginVM>();  
SimpleIoc.Default.Register<MainWindowVM>();  

При успешном входе в системуMainWindow показано и Login закрыто.Но когда я вышел из системы MainWindow, чтобы снова показать Login, я столкнулся с InvalidOperationException Cannot set Visibility or call Show, ShowDialog, or WindowInteropHelper.EnsureHandle after a Window has closed. Поэтому я подумал, что мне нужно "очистить" экземпляр, созданный SimpleIoC, отменив его регистрацию в событии закрытия окна.

public class ViewModelBaseEx : ViewModelBase
{
    protected SimpleIoc Ioc
    {
        get { return SimpleIoc.Default; }
    }

    protected virtual void Unregister<T>() where T : class
    {
        Cleanup();

        if (Ioc.IsRegistered<T>())
        {
            // Attempt to remove instance
            Ioc.Unregister<T>(); 

            // If i still need to show this window again, 
            // shouldn't i need to have this instance available? (not sure)
            Ioc.Register<T>();   
        }                
    }        
}

Увы, описанный выше обходной путь не сработал, и теперь я не знаю, что делать.

  1. Каковы достоинства / недостатки моего подхода?
  2. Какобрабатывать динамический экземпляр с контейнером IoC?

ОБНОВЛЕНИЕ

Регистрация после отмены регистрации кажется необходимой, так как тип не может быть найден, если оставить его только незарегистрированным.Что касается проблемы, кажется, мне также нужно отменить регистрацию типа View.Поэтому я добавляю немного кода в View (Окно)

private void MainWindow_Closed(object sender, EventArgs e)
{
    SimpleIoc.Default.Unregister<IMainWindowView>();
    SimpleIoc.Default.Register<IMainWindowView, MainWindow>();
}

Пока все отлично работает, приемлем ли этот подход?

...