Вы используете шаблон Service Locator, в котором вы регистрируете сервисы, передаете ссылку на контейнер и явно вызываете resol для всего вашего кода.Если вы совершите быструю экскурсию по Castle Windsor wiki , они не рекомендуют использовать этот контейнер.
Как правило, вы должны зарегистрировать все типы (через установщики), разрешить только один корневой объект.(может быть, ваш основной вид, может быть, какой-то код стиля запуска / контроллера MVC), и пусть все остальное будет разрешено контейнером.В следующий раз, когда вы вызовете контейнер, почти всегда будет container.Dispose
, когда ваше приложение завершится.
См. Вики-страницу Windsor, касающуюся шаблона трех вызовов .
Если вы обнаружите случаи, когда вам нужно извлечь из контейнера во время выполнения для создания конкретных экземпляров (где вы должны передать определенные параметры для создания этого экземпляра), используйте Типизированное средство фабрики вместо непосредственного разрешения зависимостей.
MVVM с Windsor:
В моем первом приложении MVVM, которое я написал с помощью Windsor (только что закончил первую версию), я просто зарегистрировал свой основной вид и модель вида без указанияобраз жизни.По умолчанию они были одиночными.
Представление взяло экземпляр модели представления в качестве обязательной зависимости (в конструкторе) и использовало его для установки контекста данных.Я сделал это с помощью code-behind, потому что это было ненавязчиво и безболезненно.
// In my program I used interfaces for everything. You don't actually have to...
public interface IMainView
{
void Show();
}
public class MainView : Window, IMainView
{
public MainView(IMainViewModel viewModel)
{
Initialize();
this.DataContext = viewModel;
}
}
public interface IMainViewModel
{
int SomeProperty { get; set; }
ICommand ShowSubViewCommand { get; }
// ...
}
public class MainViewModel : IMainViewModel
{
public MainViewModel(SomeOtherSubComponent subComponent)
{
this.subComponent = subComponent;
// ...
}
// ...
}
Там, где у меня были подвиги, для которых я хотел создать несколько экземпляров, я регистрировал их с переходным жизненным циклом.Затем я создал фабрику представлений и фабрику моделей представлений и использовал их для получения экземпляров вложенного представления и вспомогательной модели представления из родительского представления.Я зарегистрировал обработчик событий для события закрытия представления и вызвал метод Release
на фабричных классах.
public interface ISubView
{
void Show();
event Action OnDismissed;
}
public class SubView : Window, ISubView
{
public SubView(ISubViewModel viewModel)
{
Initialize();
this.DataContext = viewModel;
// Would do this in the view model,
// but it is a pain to get Window.Close to call an ICommand, ala MVVM
this.OnClose += (s, a) => RaiseDismissed();
}
public event Action OnDismissed;
private void RaiseDismissed()
{
if(OnDismissed != null)
OnDismissed();
}
}
public interface ISubViewModel
{
string SomeProperty { get; }
// ...
}
// Need to create instances on the fly, so using Typed Factory facility.
// The facility implements them, so we don't have to :)
public interface IViewFactory
{
ISubView GetSubView(ISubViewModel viewModel);
void Release(ISubView view);
}
public interface IViewModelFactory
{
ISubViewModel GetSubViewModel();
void Release(ISubViewModel viewModel);
}
// Editing the earlier class for an example...
public class MainViewModel : IMainViewModel
{
public MainViewModel(IViewFactory viewFactory, IViewModelFactory viewModelFactory)
{
this.viewFactory = viewFactory;
this.viewModelFactory = viewModelFactory;
// Todo: Wire up ShowSubViewCommand to call CreateSubView here in ctor
}
public ICommand ShowSubViewCommand { get; private set; }
private void CreateSubView()
{
var viewModel = viewModelFactory.GetSubViewModel();
var view = viewFactory.GetSubView(viewModel);
view.OnDismissed += () =>
{
viewModelFactory.Release(viewModel);
viewFactory.Release(view);
};
view.Show();
}
// Other code, private state, etc...
}
В конце всего этого единственные вызовы контейнера:
void App_Startup()
{
this.container = new WindsorContainer();
container.Install(Configuration.FromAppConfig());
var mainView = container.Resolve<IMainView>();
mainView.Show();
}
public override OnExit()
{
container.Dispose();
}
Преимущество всей этой оснастки заключается в том, что она не зависит от контейнера (и может использоваться без контейнера), очевидно, какие зависимости принимает каждый из моих компонентов, а большая часть моего кода никогда не используется.должны спросить о его зависимостях.Зависимости просто передаются каждому компоненту по мере необходимости.