C# Mediatr:减少DI和x27的数量;不规则物体
我有很多命令和查询,大多数都需要相同的接口来完成不同的事情。有没有可能减少我的每一个处理程序都需要的混乱,并且这种混乱会一次又一次地重复C# Mediatr:减少DI和x27的数量;不规则物体,c#,dependency-injection,.net-core,autofac,mediatr,C#,Dependency Injection,.net Core,Autofac,Mediatr,我有很多命令和查询,大多数都需要相同的接口来完成不同的事情。有没有可能减少我的每一个处理程序都需要的混乱,并且这种混乱会一次又一次地重复 public class GetCoinByIdQueryHandler : IRequestHandler<GetCoinByIdQuery, CoinModel> { private readonly EventsContext context; private readonly ICacheClient cache;
public class GetCoinByIdQueryHandler : IRequestHandler<GetCoinByIdQuery, CoinModel>
{
private readonly EventsContext context;
private readonly ICacheClient cache;
private readonly ILogger logger;
private readonly IMapper mapper;
private readonly Settings settings;
public GetCoinByIdQueryHandler(
EventsContext context, ICacheClient cache, ILogger logger,
IMapper mapper, IOptions<Settings> settings)
{
this.context = context;
this.cache = cache;
this.logger = logger;
this.mapper = mapper;
this.settings = settings.Value;
}
}
公共类GetCoinByIdQueryHandler:IRequestHandler
{
私有只读事件上下文上下文;
专用只读iCache客户端缓存;
专用只读ILogger记录器;
专用只读IMapper映射器;
私人只读设置;
公共GetCoinByIdQueryHandler(
EventsContext上下文、ICacheClient缓存、ILogger记录器、,
IMapper映射器,IOPS设置)
{
this.context=上下文;
this.cache=cache;
this.logger=记录器;
this.mapper=mapper;
this.settings=settings.Value;
}
}
这可能与Mediatr没有直接关系,但我正在寻找一种更优雅的方法,将所有常见的参数简化为一个DID参数
如果有什么不同,我会使用Autofac作为我的DI容器
编辑:可能让所有处理程序从基类继承并在基类中继承的基类访问所有接口,并将它们设置为基类上的属性,但我不知道如何实现这一点
编辑2:Autofac有属性注入,但这似乎不是正确的方法,所以使用Mediatr的人,你如何处理一遍又一遍地重复自己。我所看到的每一个使用Mediatr的开源项目似乎都没有解决重复自己的问题。当我发现自己处于几个处理程序有许多共同依赖关系的情况下,我看了两件事:
公共接口IProvideCacheKey
{
字符串缓存键{get;}
}
然后,我们可以更改GetCoinByIdQuery
以实现该新接口:
公共类GetCoinByIdQuery:IRequest,IProvideCacheKey
{
公共int Id{get;set;}
公共字符串CacheKey=>$“{GetType().Name}:{Id}”;
}
接下来,我们需要创建负责缓存的MediatR行为。这使用ASP.NET Core中提供的功能,完全是因为我不知道您的ICacheClient
接口的定义:
公共类缓存行为:IPipelineBehavior
TRequest所在地:IProvideCacheKey,IRequest
{
专用只读IMemoryCache\u缓存;
公共缓存行为(IMemoryCache缓存)
{
_缓存=缓存;
}
公共异步任务句柄(TRequest请求、CancellationToken CancellationToken、RequestHandlerDelegate next)
{
//如果我们已经找到了要查找的内容,请签入缓存
var cacheKey=request.cacheKey;
if(_cache.TryGetValue(cacheKey,out var cachedResponse))
{
返回缓存响应;
}
//如果没有,则执行管道的其余部分,并将结果添加到缓存中
var response=wait next();
_cache.Set(cacheKey,response);
返回响应;
}
}
最后,我们需要向Autofac注册该行为:
builder
.RegisterGeneric(类型(缓存行为))
.As(类型(IPipelineBehavior))
.InstancePerDependence();
现在,缓存是一个跨领域的问题,它的实现存在于一个类中,使得它易于更改和测试
我们可以对不同的事情应用相同的模式,让处理程序只负责业务逻辑。@General Mediatr非常适合请求/响应,但正如您所看到的,每个commandhandler都需要我反复重复上述内容。发布这个问题后,我意识到AutoFac具有属性注入功能,但这将是另一个兔子洞。我想继续使用Mediatr,但要注意上述问题。以下是一些有趣的文章供您阅读:、和。@steven谢谢,非常有用的文章我完全同意,缓存和日志记录之类的事情应该使用行为来完成。我已经在常规日志记录中使用了行为,但是我将在命令中执行的日志记录是从缓存还是数据库中检索对象。你的答案在各方面都很完美,因为我现在可以将行为应用到缓存中(我甚至没有想过)。在给出的例子中。根据您给我的示例,如何在日志记录行为和缓存之间创建通信,以便在缓存找不到它时,我告诉日志记录器创建日志。第二个问题,我将我的定义为
builder.RegisterGeneric(typeof(loggingbeavior)).as(typeof(IPipelineBehavior))代码>与注册行为的方式有什么不同<代码>builder.RegisterGeneric(typeof(CacheBehavior)).As(typeof(IPipelineBehavior)).InstancePerDependency()代码>第