powered by simpleCommunicator - 2.0.35     © 2025 Programmizd 02
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Di generic
60 сообщений из 60, показаны все 3 страниц
Di generic
    #40061066
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
что то подтупливаю уже или может ошибся. вообщем прошу консультации.
есть интрефейс
Код: c#
1.
2.
3.
4.
5.
6.
7.
interface BaseDto{}
class FirstDto:BaseDto{}
class SecondDto:BaseDto{}
interface IProcessor<T>
{
Task ProcessAsync(T model);
}


есть парочка реализаций
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
class FirstProcessor : IProcessor<FirstDto>
{
async Task ProcessAsync(FirstDto model)
}
class SecondProcessor : IProcessor<SecondDto>
{
async Task ProcessAsync(SecondDto model)
}


регаю как бы просто
Код: c#
1.
2.
services.AddTransient<IProcessor<FirstDto>, FirstProcessor >();
services.AddTransient<IProcessor<SecondDto>, SecondProcessor >();


но мне не нравиться использование по месту так как мне приходиться делать такое
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
class TargertClasss{
IProcessor<FirstDto> _f;
IProcessor<SecondDto> _s;
TargertClasss(IProcessor<FirstDto> f, IProcessor<SecondDto> s)
_f=f;
_s=s;
}

Task SomeAction(BaseDto){
switch (dto)
{
case FirstDto fdto: return _f.ProcessAsync(fdto);
case SecondDto sdto: return _s.ProcessAsync(sdto);
...
}
}


можно ли как то по типу объект его процессор через Di красиво процесить. или какие варики есть чтоб не писать явный свитч и n инъекций в конструкторе
...
Рейтинг: 0 / 0
Di generic
    #40061081
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Без отступов глаза ломаются вообще.
...
Рейтинг: 0 / 0
Di generic
    #40061192
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
можно ли как то по типу объект его процессор через Di красиво процесить. или какие варики есть чтоб не писать явный свитч и n инъекций в конструкторе



Сделай фэктори:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
interface IProccesorFactory
{
   IProcessor<T> GetProcessor<T>();

   Task ProcessAsync<T>(T t);
}

class ProcessorFactory : IProccesorFactory
{
   IServiceProvider _sp;

   ProcessorFactory(IServiceProvider sp) => _sp = sp;

   IProcessor<T> GetProcessor<T>() => _sp.GetRequiredService<IProcessor<T>>();

   Task ProcessAsync<T>(T t) => GetProcessor<T>().ProcessAsync(t);
 
}
...
Рейтинг: 0 / 0
Di generic
    #40061193
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu,

если хочешь динамически выбирать обработчик через рефлексию, я код позже скину, быстрй
...
Рейтинг: 0 / 0
Di generic
    #40061199
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
только суть

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
...

    Task ProcessAsync<T>(T dto) where T: BaseDto
    {
       // получаем generic-определение типа
       var processorDefinition = typeof(IProcessor<>);
       // создаём конкретный тип процессора с параметром типа <T>
       var processorType = processorDefinition.MakeGenericType(dto.GetType());
       // получаем из DI экземпляр процессора
       var processor = _serviceProvider.GetRequiredService(processorType);
       // лайфхах, получаем генерик определение метода-обёртки для вызова метода процессора
       var genericMethodInfo = this.GetType().GetMethod(nameof(this.ProcessInternalAsync), BindingFlags.Instance | BindingFlags.NonPublic);
       // определение метода с параметром <T>
       var methodInfo = methodInfo.MakeGenericMethod(aggregateType, typeof(TCommand)); 
       // вызываем наш процессор
       return methodInfo.Invoke(null, processor);      
    }

    static Task ProcessInternalAsync<T>(IProcessor<T> processor) => processor.ProcessAsync();

...



ну вот как-то так
по-хорошему можно закешировать полученные типы, но и так сойдёт
...
Рейтинг: 0 / 0
Di generic
    #40061236
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt благодарю. попробую. с факторой блин я тупо не подумал что могу ж IServiceProvider засунуть
и оттуда разрулить все..и ведь просто.
а начал в стиле думать как бы типо фитчи в dryioc <key,inservcie<>> подтащить
...
Рейтинг: 0 / 0
Di generic
    #40061245
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
а начал в стиле думать как бы типо фитчи в dryioc <key,inservcie<>> подтащить


Да ну.. такое себе решение, громоздкое и непрозрачное. Но зато не надо писать новых типов.
...
Рейтинг: 0 / 0
Di generic
    #40061251
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt да рефлекшн мой варик.. факторка тоже не зашла...у меня в channel объекты разнородные но от общего родителя и под каждого свой процессор т.е. динамически. спасибо буду раскуривать рефлекшен тут слабоват просто
...
Рейтинг: 0 / 0
Di generic
    #40061431
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ты только не смейся, но почему бы, как готовое решение, не посмотреть MediatR
...
Рейтинг: 0 / 0
Di generic
    #40061449
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Технически можно медиатР. Но это архитектурное решение, его польза раскрывается, когда либа является частью архитектуры приложения. Опять же, есть и плюсы, есть и минусы — как говорится, не все так однозначно.
...
Рейтинг: 0 / 0
Di generic
    #40061474
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Ты только не смейся, но почему бы, как готовое решение, не посмотреть MediatR

я думал о медиатор но подумал ради 1 места целую библу чет борща
...
Рейтинг: 0 / 0
Di generic
    #40061485
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
fkthat
Ты только не смейся, но почему бы, как готовое решение, не посмотреть MediatR

я думал о медиатор но подумал ради 1 места целую библу чет борща

У меня в общем-то в сарае где-то завалялась готовая подобная тема, если отыщу, то скину позже на гитхаб.
...
Рейтинг: 0 / 0
Di generic
    #40061495
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
У меня в общем-то в сарае где-то завалялась готовая подобная тема, если отыщу, то скину позже на гитхаб.


Дык медиатр тоже в исходниках, берёшь и без зазрения совести тыришь че надо себе в проект
...
Рейтинг: 0 / 0
Di generic
    #40062549
Фотография Где-то в степи
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
поробуйте такую фитчу - регистратор
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
class RegisterType
    {
        private static readonly Dictionary<Type ,Action<object>> Dictionary = new Dictionary<Type, Action<object>>();
        public static void Add<T>(Action<T> action) where T : class
        {
           Dictionary.Add(typeof(T),(Action<object>) action);
        }

        public static void Invoke<T>(T t)  where T:BaseDto
        {
            Dictionary[typeof(T)].Invoke(t);
        }
    }


целевой бы конструктор выглядел так
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
 TargertClasss(IProcessor<FirstDto> f, IProcessor<SecondDto> s)
        {
            RegisterType.Add<FirstDto>((a) =>
            {
                f.ProcessAsync(a);
            });
            RegisterType.Add<SecondDto>((a) =>
            {
                s.ProcessAsync(a);
            });
        }


ну и сам вызов
Код: c#
1.
2.
3.
4.
void SomeAction(BaseDto dto)
        {
            RegisterType.Invoke(dto);
        }


ну может типы дженериков поплывут, я ведь в слепую, ну принцип думаю ясен.
...
Рейтинг: 0 / 0
Di generic
    #40062563
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu,

Я тут на гитхаб творчество выложил, можешь вот здесь посмотреть как сделано: https://github.com/fkthat/MediatorLite
...
Рейтинг: 0 / 0
Di generic
    #40062624
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

а нафига

Task HandleMessageAsync(object message); ?

привет из прошлого )

хендлеры надо регать через какой-то конфигуратор -- не тру, олд вей, не флексибел
хендлеры железно синглтоны (

диспетчер строится на экспрешонах -- хорошо
это дело не кешируется -- плохо, вся прелесть слита в утиль

и де тесты, Билли ))
...
Рейтинг: 0 / 0
Di generic
    #40062631
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
а нафига
Task HandleMessageAsync(object message); ?
привет из прошлого )

Что-то вот это вообще не понял.

hVostt
хендлеры надо регать через какой-то конфигуратор -- не тру, олд вей, не флексибел
хендлеры железно синглтоны (

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

hVostt
диспетчер строится на экспрешонах -- хорошо
это дело не кешируется -- плохо, вся прелесть слита в утиль

Кешируется. Смотри внимательней. Там все експрешены строятся в статическом конструкторе ровно один раз.

hVostt
и де тесты, Билли ))

Ты смотрел хоть? Там 100% покрытия.
...
Рейтинг: 0 / 0
Di generic
    #40062637
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

С експрешенами там эта штука на самом деле вспомогательная просто для удобства. Обработчик может обрабатывать несколько разных типов сообщений, но приходят они в него как object. А эта шляпа просто перенаправляет его в нужный метод. А так-то ничего не мешает все это кастомно делать при желании.
...
Рейтинг: 0 / 0
Di generic
    #40062644
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

Ты знаешь, я сейчас подумал, что можно эту схему с разруливанием от object к типизированному перенести в сам медиатор и тогда от нетепизированных обработчиков вообще избавиться. Надо будет вечерком сделать :)
...
Рейтинг: 0 / 0
Di generic
    #40062870
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,
оо поизучаю сорсы для развития
...
Рейтинг: 0 / 0
Di generic
    #40062873
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
а нафига
Task HandleMessageAsync(object message); ?
привет из прошлого )

Что-то вот это вообще не понял.


Ну ты требуешь реализовать два метода у хендлера, один от T, другой принимает Object.


fkthat
hVostt
хендлеры надо регать через какой-то конфигуратор -- не тру, олд вей, не флексибел
хендлеры железно синглтоны (

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


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

fkthat
Кешируется. Смотри внимательней. Там все експрешены строятся в статическом конструкторе ровно один раз.


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


fkthat
Ты смотрел хоть? Там 100% покрытия.


посыпаю голову пеплом...
...
Рейтинг: 0 / 0
Di generic
    #40062874
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
и тогда от нетепизированных обработчиков вообще избавиться


Так я и говорю, это устаревший подход лепить к тепизированному интерфейсу нетипизированный.
...
Рейтинг: 0 / 0
Di generic
    #40062876
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Кстати думал о том, будет ли твой медиатор работать в скоупе (например контроллеры), и без скоупа (например, в фоновых сервисах, IHostedService)?
...
Рейтинг: 0 / 0
Di generic
    #40062879
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
fkthat,

Кстати думал о том, будет ли твой медиатор работать в скоупе (например контроллеры), и без скоупа (например, в фоновых сервисах, IHostedService)?

Будет, конечно. Там же никакой магии - все просто через IServiceProvider создается. Как зарегаешь так и будет создаваться. От нетипизированного я избавился.
...
Рейтинг: 0 / 0
Di generic
    #40062889
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
fkthat,

Кстати думал о том, будет ли твой медиатор работать в скоупе (например контроллеры), и без скоупа (например, в фоновых сервисах, IHostedService)?

Будет, конечно. Там же никакой магии - все просто через IServiceProvider создается. Как зарегаешь так и будет создаваться. От нетипизированного я избавился.


Да, у тебя медиатор transient..
...
Рейтинг: 0 / 0
Di generic
    #40062890
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Код: c#
1.
2.
3.
            MessageDiscovery discovery = new();
            MessageCompiler compiler = new();
            MediatorConfiguration configuration = new(discovery, compiler);



не сразу к такому привыкаешь, глаз режет )
...
Рейтинг: 0 / 0
Di generic
    #40062891
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Насчёт двойной регистрации что думаешь?
...
Рейтинг: 0 / 0
Di generic
    #40062894
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Да, у тебя медиатор transient..

Тест для скоупа написал - все работает.
https://github.com/fkthat/MediatorLite/blob/develop/test/Test.Integration/Test_Integration.cs
...
Рейтинг: 0 / 0
Di generic
    #40062896
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
не сразу к такому привыкаешь, глаз режет )

На три буквы короче строка :))
...
Рейтинг: 0 / 0
Di generic
    #40062898
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
fkthat,

Насчёт двойной регистрации что думаешь?

В каком смысле?
...
Рейтинг: 0 / 0
Di generic
    #40062899
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Тест для скоупа написал - все работает.


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
        [Fact]
        public async Task Run_Scoped()
        {
            ServiceCollection services = new();
            MessageLog log = new();
            services.AddSingleton(log);
            services.AddTransient<Handler1>();
            services.AddTransient<Handler2>();



Хендлеры ж не в скоупе зареганы.
...
Рейтинг: 0 / 0
Di generic
    #40062901
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
fkthat,

Насчёт двойной регистрации что думаешь?

В каком смысле?


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
            services.AddSingleton(log);
            services.AddTransient<Handler1>(); // РАЗ
            services.AddTransient<Handler2>();

            services.AddMediator(configure => {
                configure.AddHandler<Handler1>();  // ДВА
                configure.AddHandler<Handler2>();
            });
...
Рейтинг: 0 / 0
Di generic
    #40062902
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
fkthat
пропущено...

В каком смысле?


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
            services.AddSingleton(log);
            services.AddTransient<Handler1>(); // РАЗ
            services.AddTransient<Handler2>();

            services.AddMediator(configure => {
                configure.AddHandler<Handler1>();  // ДВА
                configure.AddHandler<Handler2>();
            });



Первая регистрация просто регает в DI, а вторая регает в самом медиаторе. Они на самом деле по сути не связаны, поэтому я не стал заморачиваться их объединять.
...
Рейтинг: 0 / 0
Di generic
    #40062904
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Первая регистрация просто регает в DI, а вторая регает в самом медиаторе. Они на самом деле по сути не связаны, поэтому я не стал заморачиваться их объединять.


Ок. Если регать по второму разу всё заранее задача конечно намного упрощается, по сути это читерство )
...
Рейтинг: 0 / 0
Di generic
    #40062905
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
services.AddSingleton(log);
            services.AddTransient<Handler1>(); // РАЗ
            services.AddTransient<Handler2>();

            services.AddMediator(configure => {
                configure.AddHandler<Handler1>();  // ДВА
                configure.AddHandler<Handler2>();
            });




Просто еще дело в том, что может захотеться написать как-нибудь допустим вообще так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
services.AddSingleton(log);
services.AddTransient<Handler1>(sp => new Handler1(blablabla)); // кастомное создание
services.AddSingleton<Handler2>(); // синглетон

services.AddMediator(configure => {
    configure.AddHandler<Handler1>();  // ДВА
    configure.AddHandler<Handler2>();
});



И если все это объединять с AddHandler чтобы дважды не вызывать, то надо будет все мыслимые опции реализовывать в нем.
...
Рейтинг: 0 / 0
Di generic
    #40062906
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
И если все это объединять с AddHandler чтобы дважды не вызывать, то надо будет все мыслимые опции реализовывать в нем.


Ты не понял. Тебе достаточно зарегать хендлер в DI.

Т.е. тебе экстеншен нужен типа:

Код: c#
1.
2.
3.
4.
public static AddHandler<THandler>(this IServiceCollection services)
{
    ... зарегать все интерфейсы хендлера в DI
}
...
Рейтинг: 0 / 0
Di generic
    #40062907
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

Тут дело еще и в том, что AddHandler он с DI вообще никак не связан - его можно совершенно без DI использовать.
...
Рейтинг: 0 / 0
Di generic
    #40062908
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Если без экстеншенов то так:

Код: c#
1.
services.AddSingleton<IMessageHandler<Message1>, Handler1>();
...
Рейтинг: 0 / 0
Di generic
    #40062909
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Тут дело еще и в том, что AddHandler он с DI вообще никак не связан - его можно совершенно без DI использовать.


Код: c#
1.
2.
3.
4.
5.
6.
    public class Mediator : IMediator
    {
        private readonly IServiceProvider _serviceProvider;
        private readonly IMediatorConfiguration _configuration;

        public Mediator(IServiceProvider serviceProvider, IMediatorConfiguration configuration)



У тебя в самом медиаторе DI ))
То, что AddHandler не связан с DI просто приводит к двойной регистрации, и там и там.
...
Рейтинг: 0 / 0
Di generic
    #40062910
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Ты не понял. Тебе достаточно зарегать хендлер в DI.

Надо будет подумать. Пожалуй, можно в AddMediator смотреть какие хендлеры зареганы в DI и просто регать их в медиаторе.
...
Рейтинг: 0 / 0
Di generic
    #40062911
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Надо будет подумать. Пожалуй, можно в AddMediator смотреть какие хендлеры зареганы в DI и просто регать их в медиаторе.


Так не надо регать ничаво в медиаторе )))
У тебя медитор может достать хендлер из DI, зачем ему чё-то регать?
...
Рейтинг: 0 / 0
Di generic
    #40062912
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
fkthat
Тут дело еще и в том, что AddHandler он с DI вообще никак не связан - его можно совершенно без DI использовать.


Код: c#
1.
2.
3.
    public class Mediator : IMediator
    {
        private readonly IServiceProvider _serviceProvider;




?

Ха. Так вообще-то, кстати, IServiceProvider напрямую с DI тоже не связан. Достаточно посмотреть в какой сборке он объявлен. Это же по сути просто абстрактный "сервис провайдер". Он в дотнете еще с первой версии "обычного" фреймворка был.

https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider?view=net-5.0

авторNamespace:System
Assemblies: mscorlib.dll, System.ComponentModel.dll
...
Рейтинг: 0 / 0
Di generic
    #40062913
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Ну это лирика, понятно что это DI, а если это не DI, то это грибы.

Вот я код приводил в топике:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
...

    Task ProcessAsync<T>(T dto) where T: BaseDto
    {
       // получаем generic-определение типа
       var processorDefinition = typeof(IProcessor<>);
       // создаём конкретный тип процессора с параметром типа <T>
       var processorType = processorDefinition.MakeGenericType(dto.GetType());
       // получаем из DI экземпляр процессора
       var processor = _serviceProvider.GetRequiredService(processorType);
       // лайфхах, получаем генерик определение метода-обёртки для вызова метода процессора
       var genericMethodInfo = this.GetType().GetMethod(nameof(this.ProcessInternalAsync), BindingFlags.Instance | BindingFlags.NonPublic);
       // определение метода с параметром <T>
       var methodInfo = methodInfo.MakeGenericMethod(aggregateType, typeof(TCommand)); 
       // вызываем наш процессор
       return methodInfo.Invoke(null, processor);      
    }

    static Task ProcessInternalAsync<T>(IProcessor<T> processor) => processor.ProcessAsync();

...



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

Понятно, что добавить сюда кеширование, код подраспухнет, ещё нужны экстеншены для удобной регистрации хендлеров в контейнере. Ну и всё)
...
Рейтинг: 0 / 0
Di generic
    #40062914
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
У тебя медитор может достать хендлер из DI, зачем ему чё-то регать?

А тогда хендлеры из примера выше пришлось бы регистрировать как:
Код: c#
1.
2.
3.
4.
5.
6.
services.AddTransient<IMessageHandler<Message0>, Handler1>();
services.AddTransient<IMessageHandler<Message1>, Handler1>();
services.AddTransient<IMessageHandler<Message2>, Handler1>();
services.AddTransient<IMessageHandler<Message0>, Handler2>();
services.AddTransient<IMessageHandler<Message3>, Handler2>();
services.AddTransient<IMessageHandler<Message4>, Handler2>();


что вообще какая-то жесть.
...
Рейтинг: 0 / 0
Di generic
    #40062917
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
ещё нужны экстеншены для удобной регистрации хендлеров в контейнере.

Так вотож. И экстеншенов этих будет пара дюжин. По сути сколько методов services.AddXXX столько и екстеншенов для хендлеров понадобится. В общем сейчас вот думку думаю - дело в том, что по-любому выходит что надо не просто регать хендлер в DI а при этом еще где-то прописывать что это хендлер. Это можно автоматически определять при регистрации по наличию интерфейсов IMessageHandler<> - но это опять-таки скатывается к тому что нужен кастомный метод регистрации. И их надо дофига.
...
Рейтинг: 0 / 0
Di generic
    #40062920
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
понятно что это DI

Ну его и без ДИ использовали как-то там для всяких компонентов и т.п. - говорю же он с самого первого фреймворка существует.

https://docs.microsoft.com/en-us/dotnet/api/system.iserviceprovider?view=net-5.0#applies-to

...
Рейтинг: 0 / 0
Di generic
    #40062921
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
А тогда хендлеры из примера выше пришлось бы регистрировать как:
Код: c#
1.
2.
3.
4.
5.
6.
services.AddTransient<IMessageHandler<Message0>, Handler1>();
services.AddTransient<IMessageHandler<Message1>, Handler1>();
services.AddTransient<IMessageHandler<Message2>, Handler1>();
services.AddTransient<IMessageHandler<Message0>, Handler2>();
services.AddTransient<IMessageHandler<Message3>, Handler2>();
services.AddTransient<IMessageHandler<Message4>, Handler2>();



что вообще какая-то жесть.


Поэтому по сути и нужен экстеншен(ы) для удобной регистрации хендлеров в контейнере.
...
Рейтинг: 0 / 0
Di generic
    #40062922
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Так вотож. И экстеншенов этих будет пара дюжин.


Ну сколько? 3 штуки покроют 99% потребностей

AddHandlerSingleton<THandler>
AddHandlerTransient<THandler>
AddHandlerScoped<THandler>

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

fkthat
В общем сейчас вот думку думаю - дело в том, что по-любому выходит что надо не просто регать хендлер в DI а при этом еще где-то прописывать что это хендлер.


Зачем? Это просто сервис.


fkthat
Это можно автоматически определять при регистрации по наличию интерфейсов IMessageHandler<> - но это опять-таки скатывается к тому что нужен кастомный метод регистрации. И их надо дофига.


Ну если хочется можно сделать базовый маркер-интерфейс IMessageHandler {}.
...
Рейтинг: 0 / 0
Di generic
    #40062924
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Вот пример подобного решения:

https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/ServiceCollectionHostedServiceExtensions.cs

Сервис фоновой службы регистрируется в DI, и больше нигде.
...
Рейтинг: 0 / 0
Di generic
    #40062926
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

Пока что вот такое в голову идет:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
/// <summary>
/// Adds the mediator to the <c cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <c cref="IServiceCollection"/>.</param>
public static IServiceCollection AddMediator(this IServiceCollection services)
{
    // is a message handler interface
    bool isHandlerInterface(Type t) =>
        t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IMessageHandler<>);

    // is a message handler class
    bool isHandlerType(Type t) => t.GetInterfaces().Any(isHandlerInterface);

    // filter registered types
    var handlers = services.Select(sd => sd.ServiceType).Where(isHandlerType);

    // configuration function
    void configure(IMediatorConfigurationBuilder config) =>
        handlers.Aggregate(config, (c, h) => c.AddHandler(h));

    return services.AddMediator(configure);
}


И тогда просто:
Код: c#
1.
2.
3.
services.AddTransient<Handler1>();
services.AddTransient<Handler2>();
services.AddMediator();


единственное ограничение - AddMediator надо вызывать только после реганья хндлеров в DI. Т.е. вот так не будет работать
Код: c#
1.
2.
3.
4.
// Неправильно!
services.AddMediator();
services.AddTransient<Handler1>();
services.AddTransient<Handler2>();
...
Рейтинг: 0 / 0
Di generic
    #40062927
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Зачем? Это просто сервис.

Тут вот такой ньюанс. Если ты его зарегаешь просто как класс:
Код: c#
1.
services.AddTransient<Handler1>();


то он тебе интерфейс не разрезолвит. Т.е. что-нибудь такого типа:
Код: c#
1.
_serviceProvider.GetService<IMessageHandler<Message1>>();


просто не сработает.

Т.е. чтобы сработало тебе его надо будет при регистрации разобрать по интерфейсам и зарегать каждый интерфейс отдельно. А для этого уже нужен кастомный метод регистрации, о чем я выше как раз и писал.
...
Рейтинг: 0 / 0
Di generic
    #40062928
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Так и не понял, зафига тебе хендлеры в медиаторе.

AddMediator здесь некорректный, коллекция services на момент вызова ещё не сформирована до конца.
...
Рейтинг: 0 / 0
Di generic
    #40062929
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
Зачем? Это просто сервис.

Тут вот такой ньюанс. Если ты его зарегаешь просто как класс:
Код: c#
1.
services.AddTransient<Handler1>();



то он тебе интерфейс не разрезолвит. Т.е. что-нибудь такого типа:
Код: c#
1.
_serviceProvider.GetService<IMessageHandler<Message1>>();



просто не сработает.

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



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

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public static IServiceCollection AddHandlerTransient<THandler>(this IServiceCollection services)
   where THandler : IMessageHandler // маркер-интерфейс для тайп-чекинга
{
   var handlerInterfaces = typeof(THandler).GetInterfaces()
                .Where(itf => itf.IsGenericType && itf.GenericTypeDefinition() == typeof(IMessageHandler<>));
    foreach(var handlerInterface in handlerInterfaces)
    {
       services.AddTransient(handlerInterface, typeof(THandler));
    }
}


services.AddHandlerTransient<Handler1>();
services.AddHandlerTransient<Handler2>();



Как пример.
...
Рейтинг: 0 / 0
Di generic
    #40062930
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Код: c#
1.
AddHandlerTransient<THandler>


Ну вот. Я о том и говорил. А еще надо AddHandlerSingleton, AddHandlerScoped, и еще стопятьсот такого же учитывая все возможные перегрузки параметров.

Кстати, вот, подтверждение того, что схема с просто регистрацией не прокатит:
https://github.com/fkthat/MediatorLite/blob/feature/adv_reg/test/Test.FkThat.MediatorLite/Test_POC.cs
...
Рейтинг: 0 / 0
Di generic
    #40062961
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
fkthat,

Вот пример подобного решения:

https://github.com/dotnet/runtime/blob/main/src/libraries/Microsoft.Extensions.Hosting.Abstractions/src/ServiceCollectionHostedServiceExtensions.cs

Сервис фоновой службы регистрируется в DI, и больше нигде.

Типовой екстеншен для регистрации - все такие пишут, чего уж тут удивительного. Кстати, вообще про этот екстеншен не знал - всегда руками его просто регал.

Но тут я уже писал, что можно ведь сделать вообще с единственным кастомным екстеншеном: 22309630

fkthat
И тогда просто:
Код: c#
1.
2.
3.
services.AddTransient<Handler1>();
services.AddTransient<Handler2>();
services.AddMediator();


Т.е. никаких специальных екстеншенов для регистрации хендлеров тогда не надо - просто стандартно их регать и все. А медиатор по-любому регать надо, поэтому AddMediator() вместо AddTransient<IMediator>() никакого кода не добавляет.
...
Рейтинг: 0 / 0
Di generic
    #40062974
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat

Ну его и без ДИ использовали как-то там для всяких компонентов и т.п. - говорю же он с самого первого фреймворка существует.

Самый первый был 1,0
...
Рейтинг: 0 / 0
Di generic
    #40062988
Фотография ЕвгенийВ
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu,
А как изначально звучит задача?
Просто вижу попытку, используя абстракции языка, решить что то. Но абстракции языка тут пошли на конфликт с абстракциями библиотеки и группа товарищей (@hVostt , @fkthat) придумала новую абстракцию, дабы разрешить проблему конфликта абстракций используемых ранее....
...
Рейтинг: 0 / 0
Di generic
    #40063465
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ЕвгенийВ,

да вроде первый пост описывает. ну давай больше опишу. у меня есть набор данных с приборов которые идут стримом из нетворка в каналы(что то типо тпл но на базе каналов, подумываю про фшарп и гопак).в бд имеется мапа как интерпретировать данные с приборов. типов может быть щас 3 поэтому я преобразую данные по мапе в конкретную сущность и вызываю конкретный процессор по типу сущности чтобы запроцесить сущность. вот собственно и все.
вкрации цепочка network => pipe=> write raw local storage=> read raw from storage => tranform raw to concret enity => process enitity
...
Рейтинг: 0 / 0
Di generic
    #40064313
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Ну вот. Я о том и говорил. А еще надо AddHandlerSingleton, AddHandlerScoped, и еще стопятьсот такого же учитывая все возможные перегрузки параметров.


Тот случай, когда хотели как проще, а получилось как всегда.
Мне поэтому интерфейс регистрации Autofac нравится, там это решается одним простым расширением для билдера, нисколько не теряя в гибкости.

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

Даже в полновесном MediatR всё просто: https://github.com/jbogard/MediatR/blob/master/samples/MediatR.Examples.AspNetCore/Program.cs

Т.е. можешь свои хендлеры зарегать как тебе душе угодно, медиатр их найдёт. И это красивое решение. Регать же заранее всё в медиаторе -- сильно упрощает реализацию самой библиотеки, но усложняет использование, и по сути читерство ))
...
Рейтинг: 0 / 0
Di generic
    #40064328
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
В общем, меня бы остановил тот факт, что я вынужден одну и ту же фигню регать по два раза :)

Ну так я уже сделал, что и по два раза не нужно, и порядок регистрации не важен.
https://github.com/fkthat/MediatorLite/blob/develop/src/FkThat.MediatorLite.DependencyInjection/ServiceCollectionExtensions.cs
...
Рейтинг: 0 / 0
60 сообщений из 60, показаны все 3 страниц
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Di generic
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]