#wpf #castle-windsor #viewmodel #caliburn.micro #bootstrapping
#wpf #castle-windsor #viewmodel #caliburn.micro #загрузка
Вопрос:
Я использую загрузчик Castle Windsor в своем приложении WPF. Я попытался зарегистрировать классы моделей просмотра в контейнере windsor.
У меня есть все классы моделей просмотра в пространстве имен sample.viewmodels
Итак, я попробовал это:
_windsorContainer.Register(AllTypes.FromAssembly(GetType().Assembly)
.Where(x => x.Namespace.EndsWith("ViewModels"))
.Configure(x => x.LifeStyle.Is(LifestyleType.Singleton)));
Или этот способ для регистрации классов моделей представления в контейнере:
_windsorContainer.Register(AllTypes.FromAssembly(GetType().Assembly)
.Where(x => x.Namespace.Equals("Sample.ViewModels"))
.Configure(x => x.LifeStyle.Is(LifestyleType.Singleton)));
Этот способ не работает. Я не понимаю, почему. MainViewModel / ChildViewModel
свойство равно нулю.
Если я использую этот стиль, он работает хорошо.
////Shell
_windsorContainer.Register(
Component.For<IShellViewModel>()
.ImplementedBy<ShellViewModel>()
.LifeStyle.Is(LifestyleType.Singleton));
//Main screen
_windsorContainer.Register(
Component.For<IMainViewModel>()
.ImplementedBy<MainViewModel>()
.LifeStyle.Is(LifestyleType.Singleton));
//Child screen
_windsorContainer.Register(
Component.For<IChildViewModel>()
.ImplementedBy<ChildViewModel>()
.LifeStyle.Is(LifestyleType.Singleton));
Что плохого в первом случае?
Здесь у меня есть модели просмотра:
namespace Sample.ViewModels
{
public interface IShellViewModel
{}
public class ShellViewModel : Conductor<IScreen>.Collection.AllActive,
IShellViewModel
{
public IMainViewModel MainViewModel { get; set; }
public IChildViewModel ChildViewModel { get; set; }
protected override void OnInitialize()
{
DisplayName = "Castle Windsor Boostraper";
base.OnInitialize();
}
}
public interface IMainViewModel : IScreen
{
void SayHello();
}
public class MainViewModel : Screen, IMainViewModel
{
public void SayHello()
{
MessageBox.Show("Hello from MainViewModel");
}
}
public interface IChildViewModel : IScreen
{
void SayHello();
}
public class ChildViewModel : Screen, IChildViewModel
{
public void SayHello()
{
MessageBox.Show("Hello from ChildViewModel");
}
}
}
ОТРЕДАКТИРОВАНО:
Я немного обновил часть регистрации:
_windsorContainer.Register(AllTypes.FromAssembly(GetType().Assembly)
.Pick()
.WithService.DefaultInterface()
.Configure(x => x.LifeStyle.Is(LifestyleType.Singleton)));
Это работает, но я не уверен, что это лучший способ.
Ответ №1:
Я думаю, вы хотите сделать что-то подобное, чтобы зарегистрировать свои viewmodels в Castle Windosr
_windsorContainer.Register(AllTypes.FromThisAssembly()
.Where(x => x.Namespace.EndsWith("ViewModels"))
.WithService.AllInterfaces()
.WithService.Self()
.If(s => !s.IsAbstract)
.Configure(x => x.LifeStyle.Is(LifestyleType.Singleton)));
Но мне интересно, почему вы регистрируете свои viewmodels как одноэлементные? Я бы зарегистрировал их как временные, чтобы вы могли создавать экземпляры нескольких разных моделей представления для одного и того же представления в приложении. Я также использую интерфейс-маркер для своих viewmodels, поэтому мне не нужно полагаться на viewmodels, находясь в пространстве имен, которое заканчивается на «ViewModels».
_windsorContainer.Register(Classes
.FromThisAssembly()
.BasedOn<IViewModelBase>()
.WithServiceAllInterfaces()
.WithServiceSelf()
.LifestyleTransient()
Ответ №2:
в первом примере вы регистрируете только конкретные типы как одиночные, во втором примере вы связываете соответствующие интерфейсы с реализациями. поскольку ваши свойства предоставляют модели как интерфейсы, первая часть кода не сможет удовлетворять этим свойствам.
Комментарии:
1. Спасибо. Я немного отредактировал свою регистрационную часть кода, но я не уверен, что это лучший способ.