Pull to refresh

Comments 37

По мне так, введение в эту сферу какого -то стандарта и его продвижение — это огромный плюс по сравнению с тем что умрут все остальные опенсурс реализации. Так хоть не будет зоопарка стандартов.

Только это не стандарт, а реализация. И что делать, если она не покрывает мои потребности?

так опен сурс же, делайте пул реквесты и да прибудет!
И весь дот нет фреймворк состоит из реализаций и ничего, никто не пилит своей реализации вывода на консоль или работы http, разве только по крайней нужде.

Угу, и будет реализация, имеющая объединение всех фич — иными словами, зоопарк.

Нет, зоопарк это когда у вас куча реализаций одного и того же, а когда все действительно нужные фичи в одной, то это просто хорошая стандартная реализация.

Кто будет определять "действительно нужные фичи"?


Куча реализаций одного и того же — это не зоопарк, а свобода выбора.

Свобода выбора — это когда вы можете выбрать что вы хотите или что вам нужно. А когда вы видите массу по своей сути одинаковых решений, которые в целом равнозначны, делают одно и то же, но… слегка по-разному, это уже зоопарк. Я не могу сказать, чем, например, NInject лучше или хуже Windsor. Я сам для себя, конечно, могу выбрать какой-то любимый IoC-контейнер методом научного тыка, но бывает, приходится поддерживать и чужие проекты. И лично я бы предпочел, чтобы фича, которая продвигается как «мастхэв» процесса разработки на платформе, была реализована стандартными средствами платформы, а не кучей сторонних компонент.
Кстати насчет научного тыка и чем они отличаются. Есть неплохая статья в блоге Daniel Palm с небольшим сравнением производительности и доступных фич среди множества IoC контейнеров, довольно часто обновляется.
А когда вы видите массу по своей сути одинаковых решений, которые в целом равнозначны, делают одно и то же, но… слегка по-разному, это уже зоопарк

Нет, это все еще свобода выбора.


И лично я бы предпочел, чтобы фича, которая продвигается как «мастхэв» процесса разработки на платформе

Проблема в том, что когда DI-контейнер становится musthave для платформы — это не очень хорошо.

Стандартный контейнер определяет необходимый для .NET Core минимум способов регистрации зависимости: transient, singleton, scoped. Их реализует любой контейнер. Нужно ли было усложнить интерфейс добавления зависимостей и сделать его более богатым и совместимым со всеми фичами Simple Injector, Ninject, Castle Winsdor, Autofac и т.д?


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


Понять, запомнить и реализовать все инварианты регистрации любого из современных контейнеров очень и очень сложно, что привело бы к кучке реализаций, совместимых между собой на 90%, и порождающих такие баги, что обычные ошибки регистрации будут потом казаться ясными, как предупреждения компилятора.


В кои-то веки Майкрософт предпочла простоту универсальности.

Вопрос в том, нужно ли было вообще создавать интерфейс регистрации зависимостей.

Какой бы вы хотели видеть возможность подключения сторонних контейнеров в ASP.NET?
Наличие стандартной регистрации компонентов для DI сводит различие между всеми реализациями DI контейнеров к минимуму. Отличие будет в управлении памятью, аллокацией и построением графа зависимостей.

Одна из удачных реализаций: помечать мета-данными конструкторы / сеттеры / поля, А конфигурация всех зависимостей остается на плечах имплементации.
В результате все контейнеры смогут выполнять свою функци и не будут ограничены в том, как организовывать свою конфигурацию, а значит и возможностей для развития у них будет больше.
Одна из удачных реализаций: помечать мета-данными конструкторы / сеттеры / поля, А конфигурация всех зависимостей остается на плечах имплементации.


Сейчас так и есть, конфигурация специфичная для каждого контейнера как была так и осталась, со всем фичами характерными для каждого контейнера.
http://docs.autofac.org/en/latest/integration/aspnetcore.html

Проблема, которая возникла у вендоров состоит совсем в другом — необходимость обеспечения совместимости для интерфейсов, которые МС использует для регистрации внутренних компонентов ASP.NET Core.

Я не думаю, что метаданные обеспечат необходимый уровень гибкости, в частности, подмену произвольного сервиса или использование scoped врапперов и т.п.

Я предпочел бы мыслить об этом не в терминах "как подключить сторонний контейнер" (потому что я могу вообще не хотеть пользоваться контейнерами), а "откуда asp.net берет сервисы", и в этом случае паттерны в WebAPI были, мне кажется, весьма неплохими.

А как без него? Раньше тоже был такой интерфейс —
http://www.asp.net/web-api/overview/advanced/configuring-aspnet-web-api#services

Все что спасало сторонних вендоров от текущих проблем, что не было одного DI зашаренного между компонентами фреймворка и зависимостями определяемыми разработчиками.
Был Resolver который где-то мог использоваться фреймворком где-то нет при содании клиентских типов. И набор сервис локатор для фреймворка.

В свою очередь это порождало другую боль для разработчиков:
1. Необходимость для вендоров, а иногда и самих разработчиков переопределять стандартные фабрики и провайдеры своими и прогонять обьект через сторонний контейнер.
2. Непонятный жизненный цикл компонентов — когда надо помнить, что вот у меня эти фильтры живут как синглтоны, а эти transient, а эти Handlers опять singltones.

Мне не совсем понятен отсыл к предыдущим реализациям 'DI' в Mvc и Web Api даже на фоне текущих проблем он выглядит мягко говоря странным.
А как без него? Раньше тоже был такой интерфейс —
http://www.asp.net/web-api/overview/advanced/configuring-aspnet-web-api#services

Это не "такой же" интерфейс. Это специфичный сервис-контейнер для WebAPI, а не обобщенный DI-контейнер для любого случая. Что более важно, он делегирует свои запросы на resolve в контейнер (если такой есть), но не делегирует туда register.


Непонятный жизненный цикл компонентов — когда надо помнить, что вот у меня эти фильтры живут как синглтоны, а эти transient, а эти Handlers опять singltones.

Эта проблема не решается унифицированным DI, она решается унифицированным Resolve.

Что более важно, он делегирует свои запросы на resolve в контейнер (если такой есть), но не делегирует туда register.


В таком случае, что вам мешает делать как прежде? Использовать контейнер от стороннего вендора вне Asp.Net Core фрейморка и написать UnityGlobalFilterProvider, AutofacFilterProvider, MyControllerFactory и подключить их в IServiceCollection не мешая два контейнера?
Хотите использовать два контейнера — используйте.

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

Новый дотнет модульный, тот же асп нет конфигурируется путем регистрации и использования зависимостей. Какая этому альтернатива?

Можно использовать специфичный интерфейс регистрации, а не обобщенный контейнер.

То есть пользователь должен будет в правильном порядке зарегистрировать все сервисы необходимые MVC и EF? https://github.com/aspnet/Mvc/blob/52a7c112e8c0369b4b1626d750fb3d5b43db65bd/src/Microsoft.AspNetCore.Mvc.Core/DependencyInjection/MvcCoreServiceCollectionExtensions.cs#L121
Тогда я не очень понимаю, какой интерфейс регистрации должен использовать MVC?

Этот комментарий объясняет почему они зарегистрированы как transient, он относится к особенностям работы MVC, а не DI
Тогда я не очень понимаю, какой интерфейс регистрации должен использовать MVC?

А ему точно нужен интерфейс регистрации? Разве нельзя просто резолвить дефолтные сервисы без всякой регистрации?


Проблема в том, что регистрация — это не часть DI как паттерна, это часть конкретной контейнерной реализации DI-шаблона. Но кто-то ведь может делать DI иначе, вплоть до того, что просто иметь написанный руками composition root с конструкторами.


Этот комментарий объясняет почему они зарегистрированы как transient, он относится к особенностям работы MVC, а не DI

Да, я понимаю. И именно это и расстраивает: в итоге мы все равно должны знать, как именно работает потребляющий фреймворк (и мы не можем повлиять на то, как он работает), когда определяем жизненный цикл. Так зачем нам вообще здесь определение жизненного цикла компонента, на что оно повлияет?

Если MVC будет использовать сервисы по умолчанию вы теряете возможность менять их поведение.

Вы всегда должны знать как работает потребляющий фреймфорк, в данной модели вы можете повлиять на много больше вещей чем до этого, просто переопределяя нужные сервисы.
Если MVC будет использовать сервисы по умолчанию вы теряете возможность менять их поведение.

Конечно же, нет. По умолчанию — это когда есть способ переопределения. Как, собственно, и в MVC, и в WebAPI было сделано.


Вы всегда должны знать как работает потребляющий фреймфорк, в данной модели вы можете повлиять на много больше вещей чем до этого, просто переопределяя нужные сервисы.

Вы хотите сказать, что раньше нельзя было переопределить нужные сервисы? Или просто что теперь для переопределения доступно больше сервисов?

Можно было переопределить только те для которых команда MVC решила добавить вызов GetService.

Вот и сейчас то же самое: можно переопределить только те, которые получаются из контейнера. И это никак не зависит от регистрации, это зависит от резолва.

А что бы вы хотели переопределить из того что получается не из контейнера?

Дело не в том, что я хотел бы переопределить. Дело в том, что я бы хотел иметь возможность обойтись без DI-контейнера.

Мы работаем над тем чтобы расслабить некоторые требования, в частности требования к порядку элементов при возврате IEnumerable, из за которого и началось это обсуждение, и улучшить тесты на соответствие спецификации.
А вы это кто, простите? Команда ASP.NET в MS?
UFO just landed and posted this here
Меня тоже немного смутила эта фраза. Во многих местах статьи автор ссылается на другие записи в блогах, в т.ч. Mark Seemann Conforming Container , в которой он более подробно описывает эти недостатки(кода там правда не много). Признаюсь, я не глубоко не вникал в стаью Mark-a, но судя под этим «наименьшим общем знаменателем» он имел в виду пересечение или объединение всех фич разных IOC контенеров.
Sign up to leave a comment.

Articles