Загрузчик Caliburn Micro и Castle Windsor — Регистрация классов моделей просмотра в загрузчике

#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. Спасибо. Я немного отредактировал свою регистрационную часть кода, но я не уверен, что это лучший способ.