Mediatr:减少 DI 对象的数量

2024-01-23

我有很多命令和查询,其中大多数需要相同的接口来完成不同的事情。是否有可能如何减少我的每个处理程序都需要的这种混乱,并且一遍又一遍地重复?

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;
    }
 }

这可能与 Mediatr 没有直接关系,但我正在寻找一种更优雅的方法,将所有常见的参数减少到一个 DI'ed 参数。

如果有什么区别的话,我使用 Autofac 作为我的 DI 容器。

编辑:可能有所有处理程序继承自的基类,并且在基类中可以访问所有接口并将它们设置为基类上的属性,但我不知道如何实现这一点。

编辑2:Autofac 有属性注入,但这似乎不是正确的方法,所以使用 Mediatr 的人,你如何处理一遍又一遍地重复自己。我见过的每个使用 Mediatr 的开源项目似乎都没有解决重复自己的问题。


当我发现自己处于多个处理程序具有许多共同依赖项的情况时,我会考虑两件事:

  1. 我的管理人员是否做得太多;和
  2. 如果是这样,我是否可以在单独的类中重构一些行为

例如,在您发布的处理程序代码中,有一个缓存客户端,这可能意味着您的处理程序做了两件事:

  1. 执行业务逻辑以检索硬币;和
  2. 执行一些逻辑确实返回一个已经缓存的硬币,或者缓存您刚刚检索到的硬币

MediatR 的概念是行为 https://github.com/jbogard/MediatR/wiki/Behaviors它允许您在一个地方处理跨领域的问题;这可能适用于缓​​存、日志记录和异常处理。如果您熟悉 ASP.NET Core 中间件,它们遵循相同的概念,因为给出了每种行为:

  1. 当前请求(或 MediatR 术语中的查询);和
  2. 管道中的下一项,可以是另一个行为或查询处理程序

让我们看看如何提取行为中的缓存逻辑。现在,您不需要完全遵循此示例,它实际上只是一种可能的实现。

首先,我们将定义一个应用于需要缓存的查询的接口:

public interface IProvideCacheKey
{
    string CacheKey { get; }
}

那么我们可以改变GetCoinByIdQuery实现该新接口:

public class GetCoinByIdQuery : IRequest<CoinModel>, IProvideCacheKey
{
    public int Id { get; set; }

    public string CacheKey => $"{GetType().Name}:{Id}";
}

接下来,我们需要创建负责缓存的 MediatR 行为。这使用IMemoryCache https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-2.2ASP.NET Core 中提供的仅仅是因为我不知道你的定义ICacheClient界面:

public class CacheBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
    where TRequest : IProvideCacheKey, IRequest<TResponse>
{
    private readonly IMemoryCache _cache;

    public CacheBehavior(IMemoryCache cache)
    {
        _cache = cache;
    }

    public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
    {
        // Check in cache if we already have what we're looking for
        var cacheKey = request.CacheKey;
        if (_cache.TryGetValue<TResponse>(cacheKey, out var cachedResponse))
        {
            return cachedResponse;
        }

        // If we don't, execute the rest of the pipeline, and add the result to the cache
        var response = await next();
        _cache.Set(cacheKey, response);

        return response;
    }
}

最后,我们需要向 Autofac 注册该行为:

builder
    .RegisterGeneric(typeof(CacheBehavior<,>))
    .As(typeof(IPipelineBehavior<,>))
    .InstancePerDependency();

现在我们已经看到,缓存现在是一个跨领域的关注点,它的实现位于单个类中,使其易于更改和测试。

我们可以对不同的事物应用相同的模式,并使处理程序只负责业务逻辑。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Mediatr:减少 DI 对象的数量 的相关文章

  • 在 C++ 中使用 matlab 结构(matlab 函数调用的返回值)(由 matlab 编译器生成的库)

    你好 我有一个相当简单的 matlab 函数 例如 function MYSTRUCT myfunc MYSTRUCT prop1 test MYSTRUCT prop2 foo MYSTRUCT prop3 42 end 我用 matla
  • 如何在 .NET Framework 2.0 中模拟“Func<(Of <(TResult>)>) 委托”?

    我尝试使用这个类代码项目文章 http www codeproject com KB threads AsyncVar aspx在 VB NET 和 NET Framework 2 0 中 除了这一行之外 所有内容似乎都可以编译Privat
  • Directory.Delete 之后 Directory.Exists 有时返回 true ?

    我有非常奇怪的行为 我有 Directory Delete tempFolder true if Directory Exists tempFolder 有时 Directory Exists 返回 true 为什么 可能是资源管理器打开了
  • 如何让 Swagger 插件在自托管服务堆栈中工作

    我已经用 github 上提供的示例重新提出了这个问题 并为任何想要自己运行代码的人提供了一个下拉框下载链接 Swagger 无法在自托管 ServiceStack 服务上工作 https stackoverflow com questio
  • 提交后禁用按钮

    当用户提交付款表单并且发布表单的代码导致 Firefox 中出现重复发布时 我试图禁用按钮 去掉代码就不会出现这个问题 在firefox以外的任何浏览器中也不会出现这个问题 知道如何防止双重帖子吗 System Text StringBui
  • 复制目录内容

    我想将目录 tmp1 的内容复制到另一个目录 tmp2 tmp1 可能包含文件和其他目录 我想使用C C 复制tmp1的内容 包括模式 如果 tmp1 包含目录树 我想递归复制它们 最简单的解决方案是什么 我找到了一个解决方案来打开目录并读
  • 使用 Newtonsoft 和 C# 反序列化嵌套 JSON

    我正在尝试解析来自 Rest API 的 Json 响应 我可以获得很好的响应并创建了一些类模型 我正在使用 Newtonsoft 的 Json Net 我的响应中不断收到空值 并且不确定我的模型设置是否正确或缺少某些内容 例如 我想要获取
  • 为什么 Google 测试会出现段错误?

    我是 Google Test 的新手 正在尝试提供的示例 我的问题是 当我引入失败并设置GTEST BREAK ON FAILURE 1 或使用命令行选项 GTest 将出现段错误 我正在考虑这个例子 https code google c
  • 回发后刷新时提示确认表单重新提交。我做错了什么?

    我有一个以空白 默认状态启动的仪表板 我让用户能够将保存的状态加载到仪表板中 当他们单击 应用 按钮时 我运行以下代码 function CloseAndSave var radUpload find radUpload1ID var in
  • qdbusxml2cpp 未知类型

    在使用 qdbusxml2cpp 程序将以下 xml 转换为 Qt 类时 我收到此错误 qdbusxml2cpp c ObjectManager a ObjectManager ObjectManager cpp xml object ma
  • 在一个平台上,对于所有数据类型,所有数据指针的大小是否相同? [复制]

    这个问题在这里已经有答案了 Are char int long 甚至long long 大小相同 在给定平台上 不能保证它们的大小相同 尽管在我有使用经验的平台上它们通常是相同的 C 2011 在线草稿 http www open std
  • 如何在 Xaml 文本中添加电子邮件链接?

    我在 Windows Phone 8 应用程序中有一些大文本 我希望其中有电子邮件链接 例如 mailto 功能 这是代码的一部分
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • 无法接收 UDP Windows RT

    我正在为 Windows 8 RT 编写一个 Windows Store Metro Modern RT 应用程序 需要在端口 49030 上接收 UDP 数据包 但我似乎无法接收任何数据包 我已按照使用教程进行操作DatagramSock
  • WebSocket安全连接自签名证书

    目标是一个与用户电脑上安装的 C 应用程序交换信息的 Web 应用程序 客户端应用程序是 websocket 服务器 浏览器是 websocket 客户端 最后 用户浏览器中的 websocket 客户端通过 Angular 持久创建 并且
  • 如何从 ODBC 连接获取可用表的列表?

    在 Excel 中 我可以转到 数据 gt 导入外部数据 gt 导入数据 然后选择要使用的数据源 然后在提供登录信息后 它会给我一个表格列表 我想知道如何使用 C 以编程方式获取该列表 您正在查询什么类型的数据源 SQL 服务器 使用权 看
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐

  • 无法分配 CursorWindow

    我正在操作SQLite3我的 Android 应用程序中的数据库 我刚刚从预填充的数据库中读取数据 该数据库有 20 万行和 14 列 条目是文字 所有列的数据类型都是文本 查询最多 11 个字母的单词 例如 ABANDONMENT 效果很
  • 使用 IMongoQueryable 进行单元测试

    我正在使用 NET Core 2 0 和 NET Core MongoDB 驱动程序 我创建了一个像这样的存储库 public interface IRepository
  • Laravel 5.1 eloquent 的 with() 方法中的使用限制

    Eloquent staffGroup StaffGroup where id id gt with staffGroupRight gt first In StaffGroup Model public function staffGro
  • 获取类的实例方法列表

    我有一堂课 class TestClass def method1 end def method2 end def method3 end end 我如何获得此类中的方法列表 method1 method2 method3 TestClas
  • 将参数添加到 @keyframes 属性 Less

    我有一处房产 keyframes 我用autoprefixer编译来添加所需的前缀 我想做的是向动画名称 或任何可能的地方 添加一个参数 以将属性值更改为关键帧键 这就是我现在所拥有的 keyframes loader 0 transfor
  • Node.js Express 模块未正确加载

    Geos Mac hone georgiana npm list Users georgiana local hone email protected cdn cgi l email protection email protected c
  • (Z3Py) 函数声明有什么限制吗?

    函数声明有什么限制吗 例如 这段代码返回 unsat from z3 import def one op op arg1 arg2 if op 1 return arg1 arg2 if op 2 return arg1 arg2 if o
  • 如何让PHP使用代理设置来连接互联网?

    我位于不允许直接连接到互联网的代理服务器后面 我的所有 PHP 应用程序都无法连接到互联网进行更新检查等 我如何告诉 PHP 我的代理设置 我不想在代码中输入代理设置 我希望 PHP 本身通过全局配置设置或类似的东西使用它 如果几乎所有人的
  • 根据类中的变量对类向量进行排序[重复]

    这个问题在这里已经有答案了 我有一个类 其中有一个类型变量int储存在里面 然后我创建了一个向量 其中包含此类 然后我需要对其进行排序 然而 我的问题源于这样一个事实 我需要使用此类中存储的 int 值按升序对向量进行排序 我看过std s
  • 羽毛可以与羽毛外部管理的路线共存吗

    我们有一个大型应用程序 它使用 Express 进行休息 使用 primus 进行套接字路由 一下子全部变成羽毛是非常困难的 我正在考虑分阶段的方法 我可以采用一些路线并将它们转换为服务 因此任何新路线都将遵循服务模式 我将慢慢迁移应用程序
  • 如何处理文件路径中的空格

    我在使用以下脚本时遇到问题 我正在检查的文件路径中的空格似乎让我感到震惊 关于如何不让 PoweShell 崩溃的任何想法 Program Files x86 GC C server txt server if Test Path serv
  • 如何将数组类型作为泛型类型参数传递给 VHDL 包?

    我正在 VHDL 2008 中开发通用包 列表 该包具有元素类型的泛型类型 如果我在包中声明此元素类型的数组类型 那么它就是一个新类型 所以对于例如整数 我的新整数数组将与 ieee 库中的整数向量不兼容 所以我还需要传入数组类型 例如in
  • Pyspark:从 blob 存储加载 zip 文件

    我正在使用 Pyspark 尝试从 blob 存储中读取 zip 文件 我想在加载后解压缩文件 然后将解压缩的 CSV 写回 Blob 存储 我正在遵循此指南 该指南解释了如何在阅读后解压缩文件 https docs databricks
  • 我们可以从oracle10g程序中执行unix命令吗

    unix机器上的oracle10g 我需要在程序中执行unix命令 我该怎么做 BEGIN DBMS SCHEDULER create job job name gt SHELL JOB repeat interval gt FREQ DA
  • NGINX 将路径作为变量发送给 PHP,除非路径是文件路径

    我想将所有路径传递给index php page path 例如 domain com a b c gt index php page a b c 因此这是我的 NGINX conf 文件 location P
  • 代理似乎被 Mechanize 忽略了?

    我正在使用 http 代理和 Mechanize 模块 我初始化 mechanize 对象并设置代理 如下所示 self br mechanize Browser self br set proxies http proxyAddress
  • HTML 表单操作 method="POST" 还是 method="post"? [复制]

    这个问题在这里已经有答案了 使用非大写的 post 或大写的 POST 有什么区别吗
  • 无法将自定义转换器添加到 log4j

    下列的here http logging apache org log4j 2 x manual extending html PatternConverters 我想延长log4j通过自定义转换器 将 shiro 用户名添加到日志中 这是
  • 链接影响不同元素的 jQuery 动画

    document ready function div1 fadeIn slow div2 delay 500 fadeIn slow div3 delay 2000 fadeIn slow div4 delay 8000 fadeIn s
  • Mediatr:减少 DI 对象的数量

    我有很多命令和查询 其中大多数需要相同的接口来完成不同的事情 是否有可能如何减少我的每个处理程序都需要的这种混乱 并且一遍又一遍地重复 public class GetCoinByIdQueryHandler IRequestHandler