powered by simpleCommunicator - 2.0.35     © 2025 Programmizd 02
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Di generic
25 сообщений из 60, страница 2 из 3
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
25 сообщений из 60, страница 2 из 3
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Di generic
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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