То, как вы используете Castle.Windsor
, больше похоже на ServiceLocator, чем на контейнер IOC.
Я бы посоветовал вам использовать типизированные фабрики для разрешения ваших классов. На фабриках вам не нужно public static WindsorContainer
, потому что вы звоните Resolve
только один раз (см. Также шаблон Three-Calls ).
Начните с использования класса Bootstrapper
, где вы звоните своим IWindsorInstaller
s, и зарегистрируйте использование TypedFactoryFacility
:
public class Bootstrapper
{
public IWindsorContainer BootstrapContainer()
{
IWindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
return container.Install(new IocInstaller());
}
}
Вы можете позвонить на BootstrapContainer()
либо со своего MainView
, либо со своего App.xaml.cs
.
Теперь создайте фабрику для вашего ViewModel
:
public interface IViewModelFactory
{
IViewModel Create();
void Release(IViewModel viewModel);
}
Вам не нужно внедрять эту фабрику, Виндзор сделает это за вас.
Единственное, что вам нужно сделать, это изменить свой IocInstaller
и зарегистрировать IViewModelFactory
:
public class IocInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IViewModel>().ImplementedBy<MainWindowViewModel>().LifestyleTransient());
container.Register(Component.For<IViewModelFactory>().AsFactory());
}
}
Убедитесь, что вы знакомы с доступными Lifestyles
. По умолчанию LifestyleSingleton()
, а вы, вероятно, хотите использовать LifestyleTransient()
. Для получения дополнительной информации см. эту ссылку .
Чтобы создать ViewModel
, вы можете позвонить Resolve
в то место, где вы позвонили Bootstrapper
, и получить IViewModelFactory
:
public MainView()
{
//other stuff
Bootstrapper bootstrapper = new Bootstrapper();
IWindsorContainer container = bootstrapper.BootstrapContainer();
IViewModelFactory viewModelFactory = container.Resolve<IViewModelFactory>();
IViewModel viewModel = viewModelFactory.Create();
DataContext = viewModel;
}
Если вы хотите открыть другое окно из вашего ViewModel
сейчас, вы можете сделать это довольно легко.
Сначала создайте фабрику для вашей второй модели вида:
public interface ISecondViewModelFactory
{
ISecondViewModel Create();
void Release(ISecondViewModel secondViewModel);
}
Затем зарегистрируйте новые классы в вашем IocInstaller
:
public class IocInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
//registration for ViewModel
container.Register(Component.For<ISecondViewModel>().ImplementedBy<SecondViewModel>().LifestyleTransient());
container.Register(Component.For<ISecondViewModelFactory>().AsFactory());
}
}
Новый ISecondViewModelFactory
теперь можно установить в качестве параметра конструктора вашего ViewModel
:
public class ViewModel : INotifyPropertyChanged, IViewModel
{
private readonly ISecondViewModelFactory _secondViewModelFactory;
public ViewModel(ISecondViewModelFactory secondViewModelFactory)
{
_secondViewModelFactory = secondViewModelFactory;
}
}
Виндзор разрешает вам ISecondViewModelFactory
, поэтому вам не нужно об этом заботиться.
Затем вы можете легко создать новый SecondViewModel
и показать новое окно с SecondViewModel
в качестве DataContext
:
public void MyActionForBttnClicked()
{
//invoke second view
ISecondViewModel secondViewModel = _secondViewModelFactory.Create();
SecondWindow secondWindow = new SecondWindow();
secondWindow.DataContext = secondViewModel;
secondWindow.ShowDialog();
}