Deutsch
Germany.ruФорумы → Архив Досок→ Программирование

Инъекции при наследовании

687  1 2 все
alex445 коренной житель05.11.22 00:37
05.11.22 00:37 
Последний раз изменено 05.11.22 00:40 (alex445)

Есть базовый и потомковые классы. Хочу, чтобы в потомковых юзались некие объекты. Можно инъектировать их через конструкторы потомковых классов. Но ведь можно забыть, что в каждом потомковом должна быть такая инъекция. Тогда переношу ссылку на объект в базовый класс, инъектирую объект через конструктор базового, ну и по цепочке потомковых конструкторов передаю эту инъекцию на уровень базового. Ну а потом в потомках использую эту ссылку на объект из базового класса. Типа такого


class Base

{

public Base(IService service)

}


class Descendant

{

public Descendant(IService service) : base(service)

}


Вопрос - а никак нельзя по-другому обойтись, без портянок передачи инъекции в базовый по всей цепочке потомков, если надо ЗАСТАВИТЬ использовать этот объект в потомках? А то цепочка наследований может быть длинной, и потомков во всём дереве наследования может быть туева куча. И везде, в конструкторах всех потомков, писать base(service) как-то задалбывает. Тем более, что в реальности это выглядит куда длиннее - типа


base(IDatabaseContextService<MyDatabaseContext>)


А, да - у нас не синглетоны, а надо, чтобы в каждом объекте свой экземпляр MyDatabaseContext юзался.

#1 
AlexNek патриот05.11.22 09:22
AlexNek
NEW 05.11.22 09:22 
в ответ alex445 05.11.22 00:37
а надо, чтобы в каждом объекте свой экземпляр MyDatabaseContext юзался.

AddTransient

https://www.c-sharpcorner.com/article/understanding-addtra...


без портянок передачи инъекции в базовый по всей цепочке потомков

хотя бы serviceProvider надо передать

var service = (IFooService)serviceProvider.GetService(typeof(IFooService));


можно еще поизвращаться через статический класс, но это новые явные зависимости.

https://code-maze.com/aspnetcore-resolve-instances-with-de...

#2 
alex445 коренной житель05.11.22 11:04
NEW 05.11.22 11:04 
в ответ AlexNek 05.11.22 09:22, Последний раз изменено 05.11.22 11:08 (alex445)
AddTransient

https://www.c-sharpcorner.com/article/understanding-addtra...

Это всё "области видимости", а передавать-то всё равно придётся.


можно еще поизвращаться через статический класс, но это новые явные зависимости.

Вот по идее статический класс (фабрика там или сам экземпляр сервиса) как раз самое то. Не понимаю, почему статика это зависимость? Зависимость, это когда у вас в клиентском коде объекты конкретных типов создаются, без интерфейсов. Статика применяется по месту и не засоряет всю цепочку конструкторов или методов портянкой передачи зависимости. Статическая фабрика, возвращающая интерфейсные объекты - и от зависимостей от конкретных типов ушли, и мусор в сигнатуре методов и конструкторов не множим.


Ещё бред - в обязон хранить ссылку на переданный объект. Точнее, не само хранение, а та куча кода, которая должна быть написана ради этого. Ради одной ссылки на один сервис я должен добавить как минимум поле (а то и свойство), код передачи параметра, код присвоения параметра полю. Вот нахрена вся эта простыня очевиднейшего кода?


class Base

{

protected IService _service;


public Base(IService service)

{

_service = service;

}

}

#3 
alex445 коренной житель05.11.22 11:14
NEW 05.11.22 11:14 
в ответ alex445 05.11.22 11:04

Вроде, придумали для удобства такой атрибут и директиву @inject. Но это только для Блейзор. Накидать свойств с такой инъекцией в какой-нибудь обычной модели или вью модели MAUI или WPF я не могу ("solely applied").

#4 
AlexNek патриот05.11.22 11:16
AlexNek
NEW 05.11.22 11:16 
в ответ alex445 05.11.22 11:04
а передавать-то всё равно придётся

Так это было ко второму вопросу.


Не понимаю, почему статика это зависимость?

Как и любой синглтон. Объект зависит от его состояния.

Попался одни проект от любителя статических зависимостей. Как то его преобразовать - практически невозможно, все в таком клубке что никак не распутать.


Ещё бред - в обязон хранить ссылку на переданный объект

Есть более лучшее решение?

#5 
alex445 коренной житель05.11.22 11:21
NEW 05.11.22 11:21 
в ответ alex445 05.11.22 11:14, Последний раз изменено 05.11.22 11:22 (alex445)

Кстати, прикольный код подсмотрел в исходниках


if (injectables is null)

{

return static (_, _) => { };

}


Это что за "попа" нарисована? )) Типа лямбда с "пофиг какими параметрами" и пустым телом?

#6 
AlexNek патриот05.11.22 11:26
AlexNek
NEW 05.11.22 11:26 
в ответ alex445 05.11.22 11:21

ну так на выходе то это


private static Action<IServiceProvider, IComponent>


https://dotnetpattern.com/csharp-action-delegate - в самом конце пример

#7 
alex445 коренной житель05.11.22 12:13
NEW 05.11.22 12:13 
в ответ AlexNek 05.11.22 11:26

Так там аргументы явно есть. А тут полупопия.

#8 
  simplename постоялец05.11.22 12:25
NEW 05.11.22 12:25 
в ответ alex445 05.11.22 00:37

Делаете дифолт конструкторы потемкинских классов, которые "чтоб не забыть", приватными, и никто не забудет.

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

#9 
AlexNek патриот05.11.22 12:42
AlexNek
NEW 05.11.22 12:42 
в ответ alex445 05.11.22 12:13

А знак "_" как раз и говорит, что аргумент в игноре

https://learn.microsoft.com/ru-ru/dotnet/csharp/language-r...

#10 
alex445 коренной житель05.11.22 15:55
NEW 05.11.22 15:55 
в ответ simplename 05.11.22 12:25
Делаете дифолт конструкторы потемкинских классов, которые "чтоб не забыть", приватными, и никто не забудет.

Не понял. Что это даст?

#11 
alex445 коренной житель05.11.22 15:58
NEW 05.11.22 15:58 
в ответ AlexNek 05.11.22 12:42
А знак "_" как раз и говорит, что аргумент в игноре

https://learn.microsoft.com/ru-ru/dotnet/csharp/language-r...

А, понял. В смысле, что по вашей ссылке пример

(_, _) => 0

смысла не имеет, т.к. проще сделать ()=>0. Но относительно того, откуда я привёл первоначальный пример - там да. Т.е. такая лямбда нужна лишь для соблюдения формальности - сигнатуры возврата метода, когда на самом деле ничего возвращать не планируется.

#12 
Murr патриот05.11.22 16:43
Murr
NEW 05.11.22 16:43 
в ответ alex445 05.11.22 15:58

проще сделать ()

-----

И как ты это преобразуешь в сигнатуру метода с двумя аргументами?

#13 
alex445 коренной житель05.11.22 16:52
NEW 05.11.22 16:52 
в ответ Murr 05.11.22 16:43

Я же ответил, что для конкретной сигнатуры - конкретная "попа". Чем больше параметров, тем больше полупопий. А "пустая" лямбда - для метода без параметров.


ХЗ, по-моему, проще было бы придумать какой-нибудь оператор типа "вернуть заглушку" для случаев, когда нужно вернуть ничего не значащий объект лишь в качестве филлера, для соответствия сигнатуре. Чтобы этот оператор сам определял, для какого возврата какая заглушка, а программисту нужно было лишь написать имя оператора: типа "return empty".

#14 
AlexNek патриот05.11.22 22:49
AlexNek
NEW 05.11.22 22:49 
в ответ alex445 05.11.22 11:14
в какой-нибудь обычной модели

можно, но не нужно

https://stackoverflow.com/questions/38459625/property-inje...

#15 
Срыв покровов патриот07.11.22 08:00
NEW 07.11.22 08:00 
в ответ alex445 05.11.22 11:04
Это всё "области видимости", а передавать-то всё равно придётся.

Это скорее жизненный цикл


#16 
Срыв покровов патриот07.11.22 08:02
NEW 07.11.22 08:02 
в ответ alex445 05.11.22 11:21
Кстати, прикольный код подсмотрел в исходниках
if (injectables is null){return static (_, _) => { };}
Это что за "попа" нарисована? )) Типа лямбда с "пофиг какими параметрами" и пустым телом?

меня больше интересует, что тут значит слово static…

#17 
Программист коренной житель07.11.22 08:23
NEW 07.11.22 08:23 
в ответ alex445 05.11.22 00:37
Хочу, чтобы в потомковых юзались некие объекты. Можно инъектировать их через конструкторы потомковых классов. Но ведь можно забыть, что в каждом потомковом должна быть такая инъекция.

Несколько раз прочитал, но так и не понял, что именно забыть и как это можно забыть? Можешь пояснить свой пример кодом?


если надо ЗАСТАВИТЬ использовать этот объект в потомках?

Заставить использовавать что-либо нельзя Даже если ты через 100 потомков протащишь какую-нибудь инекцию ты никогда не сможешь гарантировать, что все потомки используют именно этот объект. Да даже если там всего 1 потомок, ты тоже не можешь этого гарантировать :)


А то цепочка наследований может быть длинной, и потомков во всём дереве наследования может быть туева куча.

Значит проблемы с архитектурой. Тут либо рефакторить, либо страдать :)


И везде, в конструкторах всех потомков, писать base(service) как-то задалбывает. Тем более, что в реальности это выглядит куда длиннее - типаbase(IDatabaseContextService<MyDatabaseContext>)

Нет, в реальности это выглядит именно "base(service)". При передаче параметров не надо указывать их тип.

#18 
alex445 коренной житель07.11.22 13:03
NEW 07.11.22 13:03 
в ответ Срыв покровов 07.11.22 08:02, Последний раз изменено 07.11.22 13:05 (alex445)
меня больше интересует, что тут значит слово static…

Это что-то из последних версий Сишарпа. Понамудрили, блин... Через пару лет откроешь чужой код, написанный по последней моде... и закроешь с матерками. ))

Шарп превращается в ипанатство с кучей нечитаемых последовательностей знаков припенания.

#19 
alex445 коренной житель07.11.22 13:10
NEW 07.11.22 13:10 
в ответ Программист 07.11.22 08:23
Хочу, чтобы в потомковых юзались некие объекты. Можно инъектировать их через конструкторы потомковых классов. Но ведь можно забыть, что в каждом потомковом должна быть такая инъекция.

Несколько раз прочитал, но так и не понял, что именно забыть и как это можно забыть? Можешь пояснить свой пример кодом?

Есть идея, что в каждом потомке надо использовать внешний объект-сервис определённого типа. Новый чел, пришедший делать нового потомка, может об этом не знать и начнёт невдуплять, как сервис инжектировать. Будет в методы его передавать, например. А можно "заставить" его это сделать через обязательный параметр базового конструктора. Тогда ему и в потомковом придётся эту инжекцию провести.


Заставить использовавать что-либо нельзя Даже если ты через 100 потомков протащишь какую-нибудь инекцию ты никогда не сможешь гарантировать, что все потомки используют именно этот объект. Да даже если там всего 1 потомок, ты тоже не можешь этого гарантировать :)

Тогда лучше использовать не "заставить", а "подсказать, как правильно".

#20 
1 2 все