Prism
От: Tom Россия http://www.RSDN.ru
Дата: 05.12.10 18:53
Оценка:
Всем привет!

Кто нибудь сабж пробовал/использует?
Интересны впечатления, особенно если кто то уже успел пересесть на 4-ю версию.
Если используете — то с каким контейнером?
Народная мудрось
всем все никому ничего(с).
Re: Prism
От: MxMsk Португалия  
Дата: 05.12.10 19:10
Оценка: 8 (1)
Здравствуйте, Tom, Вы писали:

Tom>Кто нибудь сабж пробовал/использует?

Tom>Интересны впечатления, особенно если кто то уже успел пересесть на 4-ю версию.
Tom>Если используете — то с каким контейнером?
Используем Prism 2 вместе с контейнером Autofac. Впечатления положительные. Нравится, что данный FW не перегружен функционалом, как SCSF, и поставляется в виде исходников. Легко мигрировали на .Net 4, причем для Prism достаточно Client Profile. Какие фичи используем? Модульность, события и регионы (без discovery). Ранее использовали и команды, но сейчас для таких целей применяем Action-ы из Caliburn.
Re[2]: Prism
От: Fortnum  
Дата: 06.12.10 10:49
Оценка:
Здравствуйте, MxMsk, Вы писали:

MM>Используем Prism 2 вместе с контейнером Autofac.


А какие преимущества у Autofac перед Unity?
Re[3]: Prism
От: MxMsk Португалия  
Дата: 06.12.10 11:23
Оценка: 4 (2)
Здравствуйте, Fortnum, Вы писали:

MM>>Используем Prism 2 вместе с контейнером Autofac.

F>А какие преимущества у Autofac перед Unity?
Не слежу за развитием Unity, поэтому информация может быть немного неактуальной. В свое время я выбрал Autofac за выразительность регистрации и lazy initialization. Достоинства описал здесь
Автор: MxKazan
Дата: 26.02.10
.

Например, в Unity регистрация синглтона выглядит так:
_container.RegisterType<IMarketFeedService, MarketFeedService>(new ContainerControlledLifetimeManager())

а в Autofac:
_container.Register(c => new MarketFeedService()).As<IMarketFeedService>.SingleInstance()

читается ну просто на ура.

Регистрация через лямбды легко позволила мне регистрировать сервисы не особо парясь о порядке. В Unity того времени требовалось сразу указывать уже созданный объект.
В Unity функции регистратора и резолвера смешаны в один интерфейс IUnityContainer. В Autofac же эти функции разнесены. Кому надо регистрировать я отдаю ILifetimeScope, кому только резолвить — IComponentContext.
Re[4]: Prism
От: Fortnum  
Дата: 08.12.10 00:35
Оценка:
Здравствуйте, MxMsk, Вы писали:

MM>Например, в Unity регистрация синглтона выглядит так:

MM>
_container.RegisterType<IMarketFeedService, MarketFeedService>(new ContainerControlledLifetimeManager())

MM>а в Autofac:
MM>
_container.Register(c => new MarketFeedService()).As<IMarketFeedService>.SingleInstance()

MM>читается ну просто на ура.

Я себе сделал такую фишку:
public static class UnityContainerExtensions
{
    public static T ResolveAndRegisterInstance<T>(this IUnityContainer container)
    {
        var instance = container.Resolve<T>();

        container.RegisterInstance<T>(instance);

        return instance;
    }
}


А сейчас еще попутно статейку нашел Extend Unity and UnityContainer with Extension Methods in C# 3.0. Так что синтаксис — вопрос решаемый И, кстати, в статейке интересная фраза приводится:

A year ago there were big differences between the various frameworks, but the gap has narrowed such that for most applications any DI framework will do.


MM>Регистрация через лямбды легко позволила мне регистрировать сервисы не особо парясь о порядке. В Unity того времени требовалось сразу указывать уже созданный объект.


Да, но порядок все равно как-то должен учитываться. Можно типы собрать в коллекцию и еще один метод расширения сделать, который регистрирует коллекцию синглтонов

MM>В Unity функции регистратора и резолвера смешаны в один интерфейс IUnityContainer. В Autofac же эти функции разнесены. Кому надо регистрировать я отдаю ILifetimeScope, кому только резолвить — IComponentContext.


Это, конечно, ход в правильном направлении. В Unity, а точнее в Microsoft.Practices.ServiceLocation есть ServiceLocator, который по сути есть IComponentContext, если я правильно понял.

— cut —

У меня сейчас три проблемы. Не проблемы даже, а пожелания или непонятности:

1. Мне надо резолвить объект таким образом, чтобы если экземпляр не создан, он создавался обязательно в новом потоке. Extension-методы здесь не помогают. Предполагаю, что надо написать какой-нибудь Unity-extension, а к классу применить самописный атрибут, но пока еще не сделал. Сейчас обхожу тупо принудительно создавая экземпляр в новом потоке в заранее отведенном месте.

2. Пока что я совсем не использую именованные регистрации в контейнере. В частности для дочерних ViewModel'ей я вместо этого создаю дочерние контейнеры, которые сохраняю в полях этих ViewModel'ей, а сами эти ViewModel'и в коллекции родительской ViewModel'и, которая в свою очередь представляет собой синглтон в родительском контейнере. Не знаю, правильно ли, но пока работает и модульность на ура.

3. Хочется иметь контейнер в виде контекста, а не в виде параметра конструктора объекта. Потому что больно мозолит глаза этот параметр. Не знаю пока как это сделать, но хотелось бы. Причем если с одним самым первым контейнером в Unity вроде все понятно — ServiceLocator.Current.GetInstance<IUnityContainer>, то как быть с дочерними, не понятно.
Re[5]: Prism
От: Fortnum  
Дата: 08.12.10 00:50
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>У меня сейчас три проблемы. Не проблемы даже, а пожелания или непонятности:


И еще одна есть проблемка/непонятность — как быть с базовыми всяческими типами и наследованием. Т.е. объявил IMyInterface/MyClass, зарегистрировал в контейнере, затем создал пользователя, и этот пользователь может вытащить экземпляр MyClass'а по ключу IMyInterface. ОК.

Но тут я делаю нечто более развитое MyClass2, например. И для этого создаю IMyInterface2 : IMyInterface. Очевидно, что старый пользователь MyUserClass должен суметь вытащить это нечто более развитое по ключу IMyInterface, а следовательно это нечто более развитое MyClass2 надо регистрировать в контейнере по двум ключам IMyInterface и IMyInterface2.

Развивая ситуацию в шаблон, надо написать extension-метод, который регистрирует тип TTo по ключу TFrom, но после этого пытается тот же TTo зарегистрировать еще и по всей линейке предков TFrom.
Re[5]: Prism
От: MxMsk Португалия  
Дата: 08.12.10 07:56
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>А сейчас еще попутно статейку нашел Extend Unity and UnityContainer with Extension Methods in C# 3.0. Так что синтаксис — вопрос решаемый И, кстати, в статейке интересная фраза приводится:

F>A year ago there were big differences between the various frameworks, but the gap has narrowed such that for most applications any DI framework will do.
Согласен. Вопрос синтаксиса, конечно, решаемый. Просто иметь фичу из коробки всегда приятнее.

MM>>Регистрация через лямбды легко позволила мне регистрировать сервисы не особо парясь о порядке. В Unity того времени требовалось сразу указывать уже созданный объект.

F>Да, но порядок все равно как-то должен учитываться. Можно типы собрать в коллекцию и еще один метод расширения сделать, который регистрирует коллекцию синглтонов
А если эти синглтоны регистрируются из разных сборок? Как коллекцию собирать будем? В любом случае, в реализации Unity такие вещи превращаются в головную боль. Во всяком случае, так было у меня. Решение в Autofac через лямбды гораздо изящнее. Сейчас Unity подтянулся в подтверждение приведенной тобою цитаты. Как, кстати, в нем передавать параметры для резолва? Например, когда нужны аргументы для конструктора.

MM>>В Unity функции регистратора и резолвера смешаны в один интерфейс IUnityContainer. В Autofac же эти функции разнесены. Кому надо регистрировать я отдаю ILifetimeScope, кому только резолвить — IComponentContext.

F>Это, конечно, ход в правильном направлении. В Unity, а точнее в Microsoft.Practices.ServiceLocation есть ServiceLocator, который по сути есть IComponentContext, если я правильно понял.
Да, пожалуй.

F>У меня сейчас три проблемы. Не проблемы даже, а пожелания или непонятности:


F>1. Мне надо резолвить объект таким образом, чтобы если экземпляр не создан, он создавался обязательно в новом потоке. Extension-методы здесь не помогают. Предполагаю, что надо написать какой-нибудь Unity-extension, а к классу применить самописный атрибут, но пока еще не сделал. Сейчас обхожу тупо принудительно создавая экземпляр в новом потоке в заранее отведенном месте.

Как с этим в Autofac, я не знаю.

F>2. Пока что я совсем не использую именованные регистрации в контейнере. В частности для дочерних ViewModel'ей я вместо этого создаю дочерние контейнеры, которые сохраняю в полях этих ViewModel'ей, а сами эти ViewModel'и в коллекции родительской ViewModel'и, которая в свою очередь представляет собой синглтон в родительском контейнере. Не знаю, правильно ли, но пока работает и модульность на ура.

Гм. А какую задачу это решает?

F>3. Хочется иметь контейнер в виде контекста, а не в виде параметра конструктора объекта. Потому что больно мозолит глаза этот параметр. Не знаю пока как это сделать, но хотелось бы. Причем если с одним самым первым контейнером в Unity вроде все понятно — ServiceLocator.Current.GetInstance<IUnityContainer>, то как быть с дочерними, не понятно.

Это вообще врядли возможно. Разве что, если устроит ситуация, когда ссылка на контейнер будет недоступна в конструкторе.
Re[6]: Prism
От: MxMsk Португалия  
Дата: 08.12.10 08:03
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>И еще одна есть проблемка/непонятность — как быть с базовыми всяческими типами и наследованием. Т.е. объявил IMyInterface/MyClass, зарегистрировал в контейнере, затем создал пользователя, и этот пользователь может вытащить экземпляр MyClass'а по ключу IMyInterface. ОК.

F>Но тут я делаю нечто более развитое MyClass2, например. И для этого создаю IMyInterface2 : IMyInterface. Очевидно, что старый пользователь MyUserClass должен суметь вытащить это нечто более развитое по ключу IMyInterface, а следовательно это нечто более развитое MyClass2 надо регистрировать в контейнере по двум ключам IMyInterface и IMyInterface2.
F>Развивая ситуацию в шаблон, надо написать extension-метод, который регистрирует тип TTo по ключу TFrom, но после этого пытается тот же TTo зарегистрировать еще и по всей линейке предков TFrom.
Не факт, что это хорошо по части вопросов совместимости
Регистрация нескольких "типов-ключей" в Autofac выглядит так:
builder.Register(c => new MyServiceImpl(...))
    .As<IMyService1>()
    .As<IMyService2>()
    .As<IMyService3>();


И еще одна отличная фича — регистрация адаптеров:
builder.RegisterAdapter<IComponentContext, IServiceLocator>(c => new AutofacServiceLocator(c)).InstancePerLifetimeScope();

Так у нас регистрируется адаптер, который при запросе Микрософтского IServiceLocator, будет возвращать адаптер для IComponentContext из Autofac. InstancePerLifetimeScope указывает, что нужно создавать по одному адаптеру на каждый Autofac-овский контейнер.
Re[6]: Prism
От: Vladek Россия Github
Дата: 08.12.10 14:30
Оценка:
Здравствуйте, Fortnum, Вы писали:

F>Здравствуйте, Fortnum, Вы писали:


F>>У меня сейчас три проблемы. Не проблемы даже, а пожелания или непонятности:


F>И еще одна есть проблемка/непонятность — как быть с базовыми всяческими типами и наследованием. Т.е. объявил IMyInterface/MyClass, зарегистрировал в контейнере, затем создал пользователя, и этот пользователь может вытащить экземпляр MyClass'а по ключу IMyInterface. ОК.


F>Но тут я делаю нечто более развитое MyClass2, например. И для этого создаю IMyInterface2 : IMyInterface. Очевидно, что старый пользователь MyUserClass должен суметь вытащить это нечто более развитое по ключу IMyInterface, а следовательно это нечто более развитое MyClass2 надо регистрировать в контейнере по двум ключам IMyInterface и IMyInterface2.


F>Развивая ситуацию в шаблон, надо написать extension-метод, который регистрирует тип TTo по ключу TFrom, но после этого пытается тот же TTo зарегистрировать еще и по всей линейке предков TFrom.


Вы используете контейнер внедрения зависимостей правильно, если он создаётся и используется внутри только одного метода. А если вы этот контейнер таскаете по всему приложению в течении всей жизни приложения — вы наживаете себе геморрой. В Призме дело именно так обстоит?

Контейнер должен строить весь граф зависимых объектов один раз в начале жизни приложения и всё — далее он не нужен. Только в этом случае можно утверждать, что конфигурирование приложения завершено.

В данном конкретном случае проблемы нет — в MyUserClass внедряется объект по интерфейсу IMyInterface2, а не сам MyUserClass чего-то там вытаскивает по интерфейсу IMyInterface с помощью контейнера.

unity.RegisterType<IMyInterface2, MyClass2>();
unity.RegisterType<MyUserClass>(new InjectionProperty("MyInterface", new ResolvedParameter<IMyInterface2>()));
unity.RegisterType<MyUserClass2>(new InjectionProperty("MyInterface2", new ResolvedParameter<IMyInterface2>()));
Re[6]: Контейнер & MVVM
От: Fortnum  
Дата: 09.12.10 10:08
Оценка:
Здравствуйте, MxMsk, Вы писали:

F>>2. Пока что я совсем не использую именованные регистрации в контейнере. В частности для дочерних ViewModel'ей я вместо этого создаю дочерние контейнеры, которые сохраняю в полях этих ViewModel'ей, а сами эти ViewModel'и в коллекции родительской ViewModel'и, которая в свою очередь представляет собой синглтон в родительском контейнере. Не знаю, правильно ли, но пока работает и модульность на ура.

MM>Гм. А какую задачу это решает?

Задачу нахождения видом своей модели вида, а также моделью вида другой модели вида или сервиса, участвующих в сценарии. Вид резолвит свою модель и тут может быть два варианта, либо эта модель уже создана, настроена и зарегистрирована в контейнере, либо вид создает эту модель с нуля и тут же кладет в контейнер, и эта созданная видом новая модель вида всегда может быть взята и сконфигурирована. Т.о., если раньше я назначал модель вида виду через DataContext (приводя тип вида к FrameworkElement), то теперь через контейнер. Зачем, пока до конца не знаю, точнее до сих пор пытаюсь четко сформулировать что и зачем я использую, и тут я сильно торможу пока Минус, или особенность — контейнер, в частности, IUnityContainer проходит сквозь все программы красной нитью. Контейнер помогает уменьшить количество кода. Использование иерархии контейнеров сродни использованию Attached Properties у видов, только на уровне их моделей.
Re[5]: Prism
От: Fortnum  
Дата: 09.12.10 13:18
Оценка:
Здравствуйте, Fortnum, Вы писали:

MM>>Например, в Unity регистрация синглтона выглядит так:

MM>>
_container.RegisterType<IMarketFeedService, MarketFeedService>(new ContainerControlledLifetimeManager())

MM>>а в Autofac:
MM>>
_container.Register(c => new MarketFeedService()).As<IMarketFeedService>.SingleInstance()

MM>>читается ну просто на ура.

F>Я себе сделал такую фишку:

F>
F>public static class UnityContainerExtensions
F>{
F>    public static T ResolveAndRegisterInstance<T>(this IUnityContainer container)
F>    {
F>        var instance = container.Resolve<T>();

F>        container.RegisterInstance<T>(instance);

F>        return instance;
F>    }
F>}
F>


Кстати, с этими контейнерами синглтон синглтону рознь — сегодня нашел новую фишку в Unity 2.0 — HierarchicalLifetimeManager. Идея зародилась, видимо, вот здесь. Это, собственно, ради чего мне ResolveAndRegisterInstance нужен был.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.