Re[3]: Обращение к пользователю из слоя бизнес-логики
От: bl-blx Россия http://yegodm.blogspot.com
Дата: 29.03.11 10:56
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Здравствуйте, bl-blx, Вы писали:


BB>>Я думаю, DIC отличается от глобальных переменных тем, что правильный

BB>>контейнер следит за доступностью имплементаций на этапе связывания.
BB>>Поэтому невозможно получить null там, где контейнеру дана инструкция выполнить DI.

MC>Может я просто не знаю как это все правильно делается в хороших DIC контейнерах. Можете посмотреть что меня волнует в DIC в моем предыдущем посту (ответ samius'у).


MC> Хотя меня почему-то немного отталкивают эти DIC.. Ихмо они ведут к заметному
усложнению кода и снижению надежности. Например, я не очень понимаю как правильно
а точнее где) инициализировать DIC. Допустим есть UI-сборка с методом Main() в
котором мы будем регистрировать типы, а резолвить их будем например в сборке с BLL.
Если у нас одна UI-сборка, то в принципе все ок, но у меня несколько UI-сборок
использующих BLL-сборку. Соответственно, если в какой-то из них я забуду проинициализировать
DIC то в рантайме при попытке резолва могу получить TypeNotRegisteredException. Если я
добавлю новый тип в контейнер, то мне надо будет не забыть его регистрировать из всех
сборок где может выполниться код, который этот тип попытается резолвить.

В случае DIC вся ваша функциональность, включая UI, превращается в компоненты,
загружаемые в контейнер. В DIC явно такое понятие как сборка с Main() может и
вовсе отсутствовать, когда Main сидит где-то внутри DIC. Ответственность DIC —
согласно конфигурации загрузить ваши компоненты и осуществить DI везде где заявлено.
Что из себя компоненты архитектурно представляют — один класс, много классов с
фасадом, в одной сборке или в нескольких — это целиком в вашей власти. Внутри
руками ничего резолвить не нужно, поскольку после того, как контейнер закончит
работу по инициализации и связыванию компонентов всё будет разрезолвлено.
В вашем конкретном случае, при использовании DIC генераторы можно сделать
отдельными компонентами и там, где нужны внешние зависимости (например, получение
подтверждений от пользователя), указать контейнеру на необходимость DI соответствующих
сервисов. Типичные для многих контейнеров варианты DI — инжекция через аргументы
конструктора или через сеттеры.
El pueblo unido jamás será vencido.
Re: Обращение к пользователю из слоя бизнес-логики
От: huligun Россия  
Дата: 29.03.11 11:02
Оценка:
Еще можно через события реализовать.

    public class ValidateEventArgs:EventArgs
    {
        public bool IsAllowed { get; set; }
        public int Value { get; set; } 
    }

    class Base
    {
        public event EventHandler<ValidateEventArgs> Validate;

        protected void InvokeValidate(ValidateEventArgs e)
        {
            EventHandler<ValidateEventArgs> handler = Validate;
            if (handler != null) handler(this, e);
        }

        public virtual void Generate()
        {
        }
    }

    class Inherited: Base
    {
        public override void Generate()
        {
            var args = new ValidateEventArgs();
            InvokeValidate(args);

            if (args.IsAllowed)
            {
                Console.WriteLine(args.Value);
            }
        }
    }


и из UI использовать

        static void Main(string[] args)
        {
            var inherited = new Inherited();

            inherited.Validate += inherited_Validate;
            inherited.Generate();
        }

        static void inherited_Validate(object sender, ValidateEventArgs e)
        {
            if (sender is Inherited)
            {
                e.IsAllowed = true;
                e.Value = 666;
            }
        }
Re[4]: Обращение к пользователю из слоя бизнес-логики
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.03.11 11:28
Оценка: +1
Здравствуйте, adontz, Вы писали:

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


S>>Осталось сделать один шаг до классического Service Locator — вынести хранение и перебор миксинов в отдельный класс


A>А тут мы опять потеряем типизированность.


А ее и нет

foreach (IMixin mixin in mixins)
{
IItemValidatorMixin ivm = mixin as IItemValidatorMixin;

if (ivm != null)

На сколько я понимаю, IMixin — просто маркер, который едва лучше System.Object в данном случае.
Re[5]: Обращение к пользователю из слоя бизнес-логики
От: adontz Грузия http://adontz.wordpress.com/
Дата: 29.03.11 12:03
Оценка:
Здравствуйте, samius, Вы писали:

S>А ее и нет

S>

S>foreach (IMixin mixin in mixins)
S> {
S> IItemValidatorMixin ivm = mixin as IItemValidatorMixin;

S> if (ivm != null)

S>На сколько я понимаю, IMixin — просто маркер, который едва лучше System.Object в данном случае.

Да нет. Вся фишка в реализациях IMixin которые принимают типизированный анонимный делегат. Либо надо будет передавать Delegate[], а это мрак. Передашь делегат неизвестного бизнес-логике типа и будешь долго искать ошибку. Либо надо будет для каждого диалога писать класс, упаковываемый в контейнер, это лень. А так получается некоторый компромисс.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[6]: Обращение к пользователю из слоя бизнес-логики
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.03.11 12:05
Оценка:
Здравствуйте, adontz, Вы писали:

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


S>>На сколько я понимаю, IMixin — просто маркер, который едва лучше System.Object в данном случае.


A>Да нет. Вся фишка в реализациях IMixin которые принимают типизированный анонимный делегат. Либо надо будет передавать Delegate[], а это мрак. Передашь делегат неизвестного бизнес-логике типа и будешь долго искать ошибку. Либо надо будет для каждого диалога писать класс, упаковываемый в контейнер, это лень. А так получается некоторый компромисс.


Типизированный анонимный делегат можно сунуть в сервис-локатор
Re[7]: Обращение к пользователю из слоя бизнес-логики
От: adontz Грузия http://adontz.wordpress.com/
Дата: 29.03.11 12:38
Оценка:
Здравствуйте, samius, Вы писали:

S>Типизированный анонимный делегат можно сунуть в сервис-локатор


И как проверить на этапе компиляции, что делегат такого типа хоть кто-то ждёт?
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[8]: Обращение к пользователю из слоя бизнес-логики
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.03.11 12:55
Оценка:
Здравствуйте, adontz, Вы писали:

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


S>>Типизированный анонимный делегат можно сунуть в сервис-локатор


A>И как проверить на этапе компиляции, что делегат такого типа хоть кто-то ждёт?


А как это проверяется в случае с IItemValidatorMixin?
Re[9]: Обращение к пользователю из слоя бизнес-логики
От: adontz Грузия http://adontz.wordpress.com/
Дата: 29.03.11 12:57
Оценка:
Здравствуйте, samius, Вы писали:

A>>И как проверить на этапе компиляции, что делегат такого типа хоть кто-то ждёт?

S>А как это проверяется в случае с IItemValidatorMixin?

Конструктор ItemValidatorMixin принимает типизированный делегат и придоставляет для него специаолизированный интерфейс. Чтобы передать какой-то новый тип делегата надо описать нового наследника IMixin.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[10]: Обращение к пользователю из слоя бизнес-логики
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.03.11 12:58
Оценка:
Здравствуйте, adontz, Вы писали:

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


A>>>И как проверить на этапе компиляции, что делегат такого типа хоть кто-то ждёт?

S>>А как это проверяется в случае с IItemValidatorMixin?

A>Конструктор ItemValidatorMixin принимает типизированный делегат и придоставляет для него специаолизированный интерфейс. Чтобы передать какой-то новый тип делегата надо описать нового наследника IMixin.


А как понять на этапе компиляции что кто-то ждет IItemValidatorMixin в массиве IMixin?
Re[11]: Обращение к пользователю из слоя бизнес-логики
От: adontz Грузия http://adontz.wordpress.com/
Дата: 29.03.11 13:00
Оценка:
Здравствуйте, samius, Вы писали:

A>>Конструктор ItemValidatorMixin принимает типизированный делегат и придоставляет для него специаолизированный интерфейс. Чтобы передать какой-то новый тип делегата надо описать нового наследника IMixin.

S>А как понять на этапе компиляции что кто-то ждет IItemValidatorMixin в массиве IMixin?

Речь идёт о том, что такой тип делегата вообще хоть кто-то умеет ждать. А то можно параметры перепутать местами и получится фигня.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[12]: Обращение к пользователю из слоя бизнес-логики
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.03.11 13:11
Оценка:
Здравствуйте, adontz, Вы писали:

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


A>>>Конструктор ItemValidatorMixin принимает типизированный делегат и придоставляет для него специаолизированный интерфейс. Чтобы передать какой-то новый тип делегата надо описать нового наследника IMixin.

S>>А как понять на этапе компиляции что кто-то ждет IItemValidatorMixin в массиве IMixin?

A>Речь идёт о том, что такой тип делегата вообще хоть кто-то умеет ждать. А то можно параметры перепутать местами и получится фигня.
Re[12]: Обращение к пользователю из слоя бизнес-логики
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.03.11 13:12
Оценка:
Здравствуйте, adontz, Вы писали:

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


S>>А как понять на этапе компиляции что кто-то ждет IItemValidatorMixin в массиве IMixin?


A>Речь идёт о том, что такой тип делегата вообще хоть кто-то умеет ждать.

И откуда это известно на стадии компиляции? Как я понимаю, ждут массив IMixin, а что там должен быть IItemValidatorMixin — никак не обозначено. В этом плане IMixin[] ничем не лучше чем object[] или Hashtable, или ServiceLocator.
A>А то можно параметры перепутать местами и получится фигня.
Можно перепутать IItemValidatorMixin с IMyMixin42 и получится та же самая фигня.
Re[13]: Обращение к пользователю из слоя бизнес-логики
От: adontz Грузия http://adontz.wordpress.com/
Дата: 29.03.11 13:29
Оценка:
Здравствуйте, samius, Вы писали:

A>>Речь идёт о том, что такой тип делегата вообще хоть кто-то умеет ждать.

S>И откуда это известно на стадии компиляции?

Потому что наследник IMixin.

S>Как я понимаю, ждут массив IMixin, а что там должен быть IItemValidatorMixin — никак не обозначено. В этом плане IMixin[] ничем не лучше чем object[] или Hashtable, или ServiceLocator.


Лучше. В object[] можно добавить всё что угодно, в IMixin[] только наследников IMixin.

A>>А то можно параметры перепутать местами и получится фигня.

S>Можно перепутать IItemValidatorMixin с IMyMixin42 и получится та же самая фигня.

Нет, получится другая фигня. Описанная мной ошибка — банальная опечатка/описка. Описанная тобой — логическая. От логических ошибок ни мой ни твой способон е защищают, то IMixin позволяет защититься от опечаток/описок в объявлении анонимного делегата по месту вызова.
A journey of a thousand miles must begin with a single step © Lau Tsu
Re[14]: Обращение к пользователю из слоя бизнес-логики
От: samius Япония http://sams-tricks.blogspot.com
Дата: 29.03.11 13:45
Оценка:
Здравствуйте, adontz, Вы писали:

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


S>>Как я понимаю, ждут массив IMixin, а что там должен быть IItemValidatorMixin — никак не обозначено. В этом плане IMixin[] ничем не лучше чем object[] или Hashtable, или ServiceLocator.


A>Лучше. В object[] можно добавить всё что угодно, в IMixin[] только наследников IMixin.

Этим же и хуже. Когда потребуется передать decimal, придется делать спец наследника IMixin. Но по-прежнему никакой гарантии что кто-то ждет IDecimalMixin не будет.

A>>>А то можно параметры перепутать местами и получится фигня.

S>>Можно перепутать IItemValidatorMixin с IMyMixin42 и получится та же самая фигня.

A>Нет, получится другая фигня. Описанная мной ошибка — банальная опечатка/описка. Описанная тобой — логическая. От логических ошибок ни мой ни твой способон е защищают, то IMixin позволяет защититься от опечаток/описок в объявлении анонимного делегата по месту вызова.

Сформулирую так: базовый тип IMixin уменьшает риск опечатки (полностью не исключает, т.к. если есть IItem1ValidatorMixin, то опечатка все еще возможна), но затрудняет передачу других вещей.
А т.к. Hashtable и ServiceLocator — общеупотребимые и простые вещи, то я бы предпочел их, хотя бы потому что не нужно вводить новые сущности для того что бы передать делегат. Гарантию от опечаток/описок и логических ошибок дадут тесты.
Re: Обращение к пользователю из слоя бизнес-логики
От: techgl  
Дата: 29.03.11 18:28
Оценка:
Здравствуйте, MozgC, Вы писали:

MC>Получается, что чтобы передать callback данному методу, его надо передать сначала из UI классу SupplierService, тот передаст его фабричному методу GetSupplierOrderGenerator, тот передаст его уже классу StockOrderGenerator. Это при том, что остальным классам наследникам от SupplierOrderGenerator этот коллбек вообще не нужен, но из-за StockOrderGenerator мы его будем тянуть по всей цепочке. Не нравится мне это.

MC>Что посоветуете?
Нужно делать отдельный компонент/сервис, на подобие Manual Task из BPEL. Твой Generator просто формирует ему Задачу (Task), и ждет ее выполнения. И ему не важно, будет это толстый/тонкий клиент или еще что-то. Тогда не нужно будет ничего между слоями передавать, ибо Задача является абстракцией, не завязанной на конкретный способ выполнения. Про нее известно только то, что она будет выполнена с участием живого человека (оператора).
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.