Asp.net core利用MediatR进程内发布/订阅详解
编程学习 2021-07-04 22:41www.dzhlxh.cn编程入门
这篇文章主要给大家介绍了关于Asp.net core利用MediatR进程内发布/订阅的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Asp.net core具有一定的参考学习价值,需要的朋友们狼蚁网站SEO优化来一起学习学习吧
1、背景
最近,一个工作了一个月的同事离职了,所做的东西怼了过来。一看代码,惨不忍睹,一个方法六七百行,啥也不说了吧,实在没法儿说。介绍下业务场景吧,一个公共操作A,业务中各个地方都会做A操作,正常人正常思维应该是把A操作提取出来封装,其他地方调用,可这哥们儿偏偏不这么干,代码到处复制。仔细分析了整个业务之后,发现是一个典型的事件/消息驱动型,或者叫发布/订阅型的业务逻辑。鉴于系统是单体的,所以想到利用进程内发布/订阅的解决方案。记得很久之前,做WPF时候,用过Prism的EventAggregator(是不是暴露年龄了。。。),那玩意儿不知道现在还在不在,支不支持core,目前流行的是MediatR,跟core的集成也好,于是决定采用MediatR。
2.Demo代码
Startup服务注册:
public void ConfigureServices(IServiceCollection services) { services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2); services.AddScoped<IService1, Service1>(); services.AddScoped<IService2, Service2>(); services.AddScoped<IContext, Context>(); services.AddMediatR(typeof(SomeEventHandler).Assembly); }
服务1:
public class Service1 : IService1 { private readonly ILogger _logger; private readonly IMediator _mediator; private readonly IContext _context; private readonly IService2 _service2; public Service1(ILogger<Service1> logger, IMediator mediator, IContext context) { _logger = logger; _mediator = mediator; _context = context; //_service2 = service2; } public async Task Method() { _context.CurrentUser = "test"; //await _service2.Method(); //_service2.Method(); await _mediator.Publish(new SomeEvent()); //_mediator.Publish(new SomeEvent()); await Task.CompletedTask; } }
可以看到,在服务1的method方法中,发布了SomeEvent事件消息。
服务2代码:
public class Service2 : IService2 { private readonly ILogger _logger; private readonly IContext _context; public Service2(ILogger<Service2> logger, IContext context) { _logger = logger; _context = context; } public async Task Method() { _logger.LogDebug("当前用户:{0}", _context.CurrentUser); await Task.Delay(5000); //_logger.LogDebug("当前用户:{0}", _context.CurrentUser); _logger.LogDebug("Service2 Method at :{0}", DateTime.Now); } }
解释下,为啥服务2 Method方法中,要等待5秒,因为实际项目中,有这么一个操作,把一个压缩程序包传递到远端,然后在远端代码操作IIS创建站点,这玩意儿非常耗时,大概要1分多钟,这里我用5s模拟,意思意思。这个5s至关重要,待会儿会详述。
再看事件订阅Handler:
public class SomeEventHandler : INotificationHandler<SomeEvent>, IDisposable { private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; private readonly IService2 _service2; public SomeEventHandler(ILogger<SomeEventHandler> logger, IServiceProvider serviceProvider, IService2 service2) { _logger = logger; _serviceProvider = serviceProvider; _service2 = service2; } public void Dispose() { _logger.LogDebug("Handler disposed at :{0}", DateTime.Now); } public async Task Handle(SomeEvent notification, CancellationToken cancellationToken) { await _service2.Method(); //using (var scope = _serviceProvider.CreateScope()) //{ // var service2 = scope.ServiceProvider.GetService<IService2>(); // await service2.Method(); /