All streams
Search
Write a publication
Pull to refresh

Comments 20

PinnedPinned comments

даже если оставить в стороне ценность вашей задумки в целом

Даже если оставить в стороне то, что вы слабо понимаете outbox в шинах, а я вполне себе делаю Metadata-Driven Framework-и в DDD/CleanArchitecture (и использую этот метод регистрации в кодогенерации. Потому что это единственный приемлемый метод в кодогенерации).

Абстракции Unity весят дай бог килобайт. Мне проще делать 1 nuget проект для 10 популярных контейнеров, чем разбивать все на RegisterByAttributes.Abstractions, RegisterByAttributes.Unity и прочее (потому что весь пакет весит дай бог 20 кб).

И еще 150+ человек, у которых ушел BoilerPlate регистраций, не будут разбираться в 3+ пакетах.

А, ну и такая мелочь, как Все популярные либы уже поддерживают добавление конфигураций\реализаций и контроллеров БЕЗ ЛИШНИХ ДЕЙСТВИЙ. (AutoMapper, MVC, etc.)

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

А что будет если есть два класса, реализующий интерфейс. При обычной регистрации будет использоваться тот, что зарегистрирован последним. Или надо использовать named регистрации. А здесь какой порядок будет?

Такая декларативная регистрация, разбросанная по коду на мой взгляд не очень удобна, поскольку требует времени на поиск и идентификацию. Я предпочитаю иметь один класс/метод, в котором все регистрации контейнеров и производятся из корня композиции (обычно Startup.ConfigureServices)

При обычной регистрации будет использоваться тот, что зарегистрирован последним. Или надо использовать named регистрации. А здесь какой порядок будет?

Тот класс, который зарегистрирован последним. Специально для Вас вышла версия 1.0.0.4. С поддержкой Keyed регистрации. Надо установить name в атрибуте для реализации.

Но на мой взгляд это плохая практика, у нас еще появляются списки имен, которые надо тащить в сервисы.

Такая декларативная регистрация, разбросанная по коду на мой взгляд не очень удобна, поскольку требует времени на поиск и идентификацию

Скорее, наоборот. Ctrl+T, Открыл интерфейс/класс и смотри.

Регистрации в контейнерах тоже не удобно - по 700 строк бойлерплейта, тяжело мержить, добавил интерфейс\реализацию - иди пиши еще 50 строк, не пропусти ничего и т.д.

по 700 строк бойлерплейта,

Так они у вас никуда не делись, только теперь размазаны по всему солюшену.

нет, читайте внимательнее.

98% регистраций - атрибут НА ИНТЕРФЕЙСЕ.

Т.е. строк точно меньше, чем при в регистрации в контейнере. Менее 1 строки на реализацию интерфейса.

Все не "размазано по солюшену", а берется из метаданных к интерфейсу\классу.

С тем же успехом можно сказать, что из-за модификаторов доступа теперь все размазано по солюшену, без единой таблицы импорта\экспорта :).

Размазано по солюшену - это именованные (Keyed) регистрации, и их получение из контейнера :). Вот где место скопления ошибок, не видимых при компиляции.

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

Атрибуты на оба интерфейса

[TypeRegistration(LifetimeManagementType.Default)]

на класс

[DerivedTypeRegistration(LifetimeManagementType.Singletone)]

Unity? В 2025? Ностальгия — мощная штука)

С версии 1.0.0.3 поддерживается регистрация типов, интерфейсы для которых могут быть где угодно. При этом регистрируются типы из сборки, где вызываешь .RegisterByAttributes();

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

  1. Зачем мне ссылка на Unity в моем проекте?

  2. У вас какая то проблема с версиями. Версия библиотеки .net7(в 2025, почему не standard?) использует зависимости для .net9, наверное большая часть проектов сломается

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

  4. Пробежался по коду, вопросы и по неймингу и по реализации. PerThread ну такое, лучше уж было и оставить Scoped.

Резюмирую: этим никто не будет пользоваться.

Всё правильно, но, по пункту №2 - "netstandard" уже давно "deprecated" и его следует использовать только если нужна совместимость с совсем уж старыми (до .NET 5) framework-ами. А так, следует либо указывать самый старый поддерживаемый (например net6.0), либо, если имеет смысл, то перечислять несколько, например, если хочется или нужно для разных TFM написать разный код или задать разные свойства MSBuild в *.csproj файле.

  1. лучше уж было и оставить Scoped.

Проект делался еще когда был unityContainer, Scoped тогда не было.

И из всего рефакторинга с тех пор только поддержка IServiceCollection и тесты.

Не нравится - делайте рефакторинг, присылайте мне на ревью.

Я буду использовать как минимум в своих Metadata-driven фреймворках )

уже существует много крутых решений для больших проектов и решение из коробки

Мне нужна регистрация по атрибутам.

Подробнее, имена проектов на Github, nuget пакетов.

И т.д., и т.п.

P.S. да, минутный рефакторинг и NetCore 2.0.

С заменой Unity на Unity.Abstractions (Теперь вы можете не тащить в свой проект Unity :) )

Напишите, как вы боритесь с размазанностью модификаторов доступа.

Проект делался еще когда был unityContainer, Scoped тогда не было.

Ну, хорошо, (даже если оставить в стороне ценность вашей задумки в целом), но зачем тут вообще Unity сейчас - вы можете объяснить? "То что мертво умереть не может" (с)? Его почти никто не использовал даже когда он был живой, а сейчас у него даже последнему коммиту в его репозиторий, по-моему, уже больше пяти лет :)

даже если оставить в стороне ценность вашей задумки в целом

Даже если оставить в стороне то, что вы слабо понимаете outbox в шинах, а я вполне себе делаю Metadata-Driven Framework-и в DDD/CleanArchitecture (и использую этот метод регистрации в кодогенерации. Потому что это единственный приемлемый метод в кодогенерации).

Абстракции Unity весят дай бог килобайт. Мне проще делать 1 nuget проект для 10 популярных контейнеров, чем разбивать все на RegisterByAttributes.Abstractions, RegisterByAttributes.Unity и прочее (потому что весь пакет весит дай бог 20 кб).

И еще 150+ человек, у которых ушел BoilerPlate регистраций, не будут разбираться в 3+ пакетах.

А, ну и такая мелочь, как Все популярные либы уже поддерживают добавление конфигураций\реализаций и контроллеров БЕЗ ЛИШНИХ ДЕЙСТВИЙ. (AutoMapper, MVC, etc.)

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

Да потрудитесь обьяснить-то!

Ладно, я искренне попытаюсь.

а я вполне себе делаю Metadata-Driven Framework-и в DDD/CleanArchitecture

При этом не понимаете, что писать в <TargetFramework>. Поменяв net7.0 на netcoreapp2.0, вы сделали хуже, потому что если у .NET 7 поддержка закончилась в мае 2024, у .NET Core 2.0 - в октябре 2018.

При этом не настроили .gitignore, чтобы не тащить в репозиторий мусор.

Вам бы основам сначала уделить внимание, а потом уже хвастаться Metadata-Driven фреймворками. И нет, у меня нет цели вам нахамить или обидеть.

Мне проще делать 1 nuget проект для 10 популярных контейнеров, чем разбивать все на RegisterByAttributes.Abstractions, RegisterByAttributes.Unity и прочее

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

Да, нужно разбивать на несколько пакетов. Unity отдельно, Microsoft DI отдельно. Нет, разбираться в 3+ пакетах никому не придётся. Кому нужен ‎RegistrationByAttributes для Microsoft DI, те по-прежнему поставят один пакет.

Если же вы сделали пакет для себя, то это уже другой вопрос. Как говорится, хозяин - барин. Но тогда не удивляйтесь фидбеку :)

И еще 150+ человек, у которых ушел BoilerPlate регистраций,

Во-первых, не ушёл. Посмею предположить, что самой частой ситуацией у разработчиков является зарегистрировать некий Service как реализацию некого IInterface. В случае Microsoft DI мне нужно написать одну строку (пусть будет синглтон):

services.AddSingleton<IInterface, Service>();

В случае RegisterByAttributes, как ни крути, вам тоже придётся эту одну строку где-то написать, ну только выглядеть она будет атрибутом. Ну и где выигрыш?

Если у вас вдруг на один интерфейс есть 4 разных сервиса - да, окей, вы выиграли и сэкономили 3 строки. Стоило ли оно того? Моё мнение - нет, потому что есть такой принцип наименьшего удивления, которому почему-то редко учат в умных книжках про принципы программирования. Суть в том, что про Microsoft DI - что это такое, как он выглядит и как им пользоваться - знает любой опытный разработчик на .NET, вы простейший web проект не сможете сделать, не наткнувшись на него. Я могу скинуть свой проект коллеге, а он уже заранее будет знать, как в него добавлять новые сервисы. А что такое RegistrationByAttributes? Какая существует веская причина, чтобы заставлять вашего пользователя разбираться в новом пакете, реализующим такую фундаментальную вещь как регистрация сервисов?

Во-вторых, лично я с возрастом начал ценить простоту. Я выберу 200 строк скучного, повторяющегося, но понятного как пять копеек кода, нежели магический чёрный ящик на 20 строк.

Все популярные либы уже поддерживают добавление конфигураций\реализаций и контроллеров БЕЗ ЛИШНИХ ДЕЙСТВИЙ. (AutoMapper, MVC, etc.)

Ну есть Scrutor на худой конец, если очень хочется автомагических регистраций.

Ну и к коду есть вопросы.

case LifetimeManagementType.Singletone:
    container.AddSingleton(baseType);

Неужели ничего не щёлкает от Singletone, когда буквально на соседней строчке находится корректный вариант?

case LifetimeManagementType.PerThread:
    container.AddScoped(baseType);

PerThread != Scoped, это разные вещи. К слову, это дополнительный довод почему пытаться натянуть один пакет на разные библиотеки DI, - не очень хорошо.

Про написание (в C# все методы пишутся в PascalCase, даже приватные) и в целом неопрятность кода уже упоминали.

При этом не понимаете, что писать в <TargetFramework>Поменяв net7.0 на netcoreapp2.0, вы сделали хуже, потому что если у .NET 7 поддержка закончилась в мае 2024, у .NET Core 2.0 - в октябре 2018.

И? Моя задача сделать либу, которая поддерживается наибольшим числом проектов. Core2.0 - самое то.

Да, нужно разбивать на несколько пакетов. Unity отдельно, Microsoft DI отдельно. Нет, разбираться в 3+ пакетах никому не придётся. Кому нужен ‎RegistrationByAttributes для Microsoft DI, те по-прежнему поставят один пакет.

Зачем? Пакеты по 100 строк кода? При этом без тяжелых зависимостей (Только Abstractions)?

Во-вторых, лично я с возрастом начал ценить простоту. Я выберу 200 строк скучного, повторяющегося, но понятного как пять копеек кода, нежели магический чёрный ящик на 20 строк.

400-800-1000 строк скучного, повторяющегося кода, который всегда вызывает конфликты при merge :)

PerThread != Scoped, это разные вещи

Тут согласен.

Моё мнение - нет, потому что есть такой принцип наименьшего удивления

Ну есть Scrutor на худой конец, если очень хочется автомагических регистраций.

Это который превращает boilerplate регистраций в еще менее поддерживаемый? И требует перерегистраций? Где истина-то?

И? Моя задача сделать либу, которая поддерживается наибольшим числом проектов. Core2.0 - самое то.

Вам нужен netstandard2.0.

Зачем? Пакеты по 100 строк кода?

Я объяснил зачем.

Либо ваш пакет полезен, либо нет, какая разница, сколько строк?

А вообще, честно говоря, проще Unity выкинуть, тогда и вопроса, делить на отдельные пакеты или нет, не будет.

400-800-1000 строк скучного, повторяющегося кода, который всегда вызывает конфликты при merge :)

Не вызывает ни в жирном монолите на несколько сотен проектов, ни в нескольких сотнях микросервисов, и это мы ещё не очень большая компания. Где-то используется Microsoft DI, где-то Autofac, в котором вы тоже регистрируете сервисы вручную, просто с другим синтаксисом. И нет никакой проблемы с конфликтами.

Не вызывает ни в жирном монолите на несколько сотен проектов, ни в нескольких сотнях микросервисов, и это мы ещё не очень большая компания. 

Да вы что, добавление 2-х разных строк в одно и то же место в файле - 100% конфликт при мерже.

Не вызывает ни в жирном монолите на несколько сотен проектов, ни в нескольких сотнях микросервисов, и это мы ещё не очень большая компания. 

Ну, расскажите нам, что у вас за git

Sign up to leave a comment.

Articles