- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我使用图书馆 MediatR
在我的ASP.NET Core
应用。
我有以下实体 Ad
:
public class Ad
{
public Guid AdId { get; set; }
public AdType AdType { get; set; }
public double Cost { get; set; }
public string Content { get; set; }
// ...
}
public enum AdType
{
TextAd,
HtmlAd,
BannerAd,
VideoAd
}
我想介绍创建新广告的功能。为此,我创建了以下命令:
public class CreateAdCommand : IRequest<Guid>
{
public AdType AdType { get; set; }
public double Cost { get; set; }
public string Content { get; set; }
public class Handler : IRequestHandler<CreateAdCommand, Guid>
{
private readonly MyDbContext _context;
public Handler(MyDbContext context)
{
_context = context;
}
public async Task<Guid> Handle(CreateAdCommand request, CancellationToken cancellationToken)
{
var ad = new Ad {AdType = request.AdType, Cost = request.Cost, Content = request.Content};
_context.Ads.Add(ad);
_context.SaveChangesAsync();
return ad.AdId;
}
}
}
这段代码很好用。但这里有一个大问题:每种广告类型在广告创建过程中都有一些额外的逻辑(例如,在创建
TextAd
类型的广告时,我们需要在广告内容中找到关键字)。最简单的解决方案是:
public async Task<Guid> Handle(CreateAdCommand request, CancellationToken cancellationToken)
{
var ad = new Ad {AdType = request.AdType, Cost = request.Cost, Content = request.Content};
_context.Ads.Add(ad);
_context.SaveChangesAsync();
switch (request.AdType)
{
case AdType.TextAd:
// Some additional logic here...
break;
case AdType.HtmlAd:
// Some additional logic here...
break;
case AdType.BannerAd:
// Some additional logic here...
break;
case AdType.VideoAd:
// Some additional logic here...
break;
}
return ad.AdId;
}
这个解决方案违反了开放封闭原则(当我创建一个新的广告类型时,我需要在
case
内部创建一个新的
CreateAdCommand
)。
CreateTextAdCommand
、
CreateHtmlAdCommand
、
CreateBannerAdCommand
、
CreateVideoAdCommand
)。这个解决方案遵循开放封闭原则(当我创建一个新的广告类型时,我需要为这个广告类型创建一个新的命令——我不需要更改现有的代码)。
public class CreateTextAdCommand : IRequest<Guid>
{
public double Cost { get; set; }
public string Content { get; set; }
public class Handler : IRequestHandler<CreateTextAdCommand, Guid>
{
private readonly MyDbContext _context;
public Handler(MyDbContext context)
{
_context = context;
}
public async Task<Guid> Handle(CreateTextAdCommand request, CancellationToken cancellationToken)
{
var ad = new Ad {AdType = AdType.TextAd, Cost = request.Cost, Content = request.Content};
_context.Ads.Add(ad);
await _context.SaveChangesAsync();
// Some additional logic here ...
return ad.AdId;
}
}
}
public class CreateHtmlAdCommand : IRequest<Guid>
{
public double Cost { get; set; }
public string Content { get; set; }
public class Handler : IRequestHandler<CreateHtmlAdCommand, Guid>
{
private readonly MyDbContext _context;
public Handler(MyDbContext context)
{
_context = context;
}
public async Task<Guid> Handle(CreateHtmlAdCommand request, CancellationToken cancellationToken)
{
var ad = new Ad {AdType = AdType.HtmlAd, Cost = request.Cost, Content = request.Content};
_context.Ads.Add(ad);
await _context.SaveChangesAsync();
// Some additional logic here ...
return ad.AdId;
}
}
}
// The same for CreateBannerAdCommand and CreateVideoAdCommand.
该方案遵循 Open Closed 原则,但违反了 DRY 原则。我怎么解决这个问题?
最佳答案
如果您坚持第二种方法,则可以利用 MediatR 'Behaviors' (https://github.com/jbogard/MediatR/wiki/Behaviors)。它们的作用类似于管道,您可以在其中将常见行为卸载到常用的处理程序中。
为此,请创建一个标记界面
interface ICreateAdCommand {}
现在让每个 concreate 命令都继承自它
public class CreateTextAdCommand : ICreateAdCommand
{
public readonly string AdType {get;} = AdType.Text
}
public class CreateHtmltAdCommand : ICreateAdCommand
{
public readonly string AdType {get;} = AdType.Html
}
/*...*/
您可以将其组合或替换为通用抽象基类,以避免重复通用属性。这取决于你。
public class CreateAdBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TReq : ICreateAdCommand
{
public CreateAdBehavior()
{
//wire up dependencies.
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var ad = new Ad {AdType = request.AdType, Cost = request.Cost, Content = request.Content};
_context.Ads.Add(ad);
await _context.SaveChangesAsync();
//go on with the next step in the pipeline
var response = await next();
return response;
}
}
现在连接这个行为。在 asp.net 核心中,这将在您的 startup.cs 中
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(CreateAdBehavior<,>));
在这个阶段,每次您的
IRequests
实现
ICreateAdCommand
,它会自动调用上面的处理程序,完成后它将调用行中的下一个行为,或者如果没有,则调用实际的处理程序。
public class CreateHtmlAdCommand : IRequest<Guid>
{
public class Handler : IRequestHandler<CreateHtmlAdCommand, Guid>
{
private readonly MyDbContext _context;
public Handler(MyDbContext context)
{
_context = context;
}
public async Task<Guid> Handle(CreateHtmlAdCommand request, CancellationToken cancellationToken)
{
// Some additional logic here ...
}
}
}
** 更新 **
public abstract class IRequestWithItems
{
public IDictionary<string, object> Items {get;} = new Dictionary<string,object>();
}
现在在您的 CreateAdBehavior 中,您可以创建广告并将其存储在字典中,以便在下一个处理程序中检索它:
var ad = { ... }
await _context.SaveChangesAsync();
items["newlyCreatedAd"] = ad;
而在实际
Task<Guid> Handle()
方法,您现在可以使用广告,而无需循环回数据库再次检索它。
关于c# - MediatR 库 : following the DRY principle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68613365/
我正在尝试创建一个类似 Twitter 的关注/关注系统。表格设计是这样的 - leader_id | following_id | is_mutual 1 |
尊敬的数据库专家/程序员: 我有一个mysql表,里面有用户信息,比如 id user_id name etc. 1 userA 2
我正在尝试设置我的 User GraphQL 模型以具有要查询的 followers 和 following 属性。但是,我无法在 Sequelize 中建立关系。我正在尝试使用 Follower 模
在我的网站上,我有一个类似 twitter 的概念,我有一个具有以下结构的用户连接表, ============================================= ==========
下面列出的区别是什么: 最佳答案 首先,你知道Meta Robots Tags吗?Meta Robots Tags 是告诉蜘蛛或爬虫要抓取或索引哪些页面。 跟随意味着:页面将被抓取。 No
我正在做一些项目,我在考虑关注者和像推特这样的关注系统。我在数据库中有成员表。我怎样才能做关注者系统。逻辑是什么?我做了类似的事情:我创建了名称跟随的新表,我有 3 行。这些行是 id、user_id
这是用于 C 代码检测。我正在尝试标记没有中断的 case 语句。当 break 语句之前有多行时,树的层次结构如下所示。这是 C 中的示例: switch (x) { case 1: i
大家好,我正在使用 MySQL 和 PHP 制作关注者/被关注系统,所以我想获取我关注的用户的所有视频并按 ID 描述排序。 数据库架构: 例如,如果我的 user_id = 1,并且如果我正在关注
我正在尝试根据#following #followers 找到一个计算推特用户“重要性”的方程式 我要考虑的事情: 1. #followers/#following越多,他越重要。 2. 在 20/2
这是我得到的错误 undefined method `followed_users?' for # 提取的源代码(大约第 3 行): 1: 2: 3: 4: 5: 6:
我有一个用户模型,可以创建关系以拥有关注者并关注其他人,我从 Rails 教程中学到的一切都非常有效。一件事是,我正在尝试通过添加能够看到其他人的关注者并能够拥有关注/关注按钮选项的选项来将其推进到下
我正在尝试通过 Twitter Javascript Api(请参阅 here )检查登录用户是否在 Twitter 上关注我。如果没有,我将显示一个关注按钮。现在我似乎无法找出命令 isFollow
我希望能够使用 iOS 5 的 Twitter API 将所有用户关注者和关注者用户名放入 NSDictionary... 不过我遇到了障碍。我不知道如何使用 Twitter API 来执行此操作..
希望在域之后但在其他任何内容之前获取值。 因此 URL 的示例是: www.domain.com/following#2 我只想从该 url 中获取后面的单词。 目前有这个可以重定向用户并在任何片段等
我有下表: 关系 id、follower_id、followee_id、状态 用户 id、姓名、电子邮件 我想查找正在关注或被特定用户关注的所有用户。 这是我到目前为止所拥有的,但速度非常慢: SEL
我是 state Management 的新手,正在使用 provider package 。产生这些类型的异常有多少种不同的原因,我该如何解决,此异常是在 didChangeDependencies
所以我在这里尝试制作一个类似 Instagram 的应用程序,但仅适用于汽车,我尝试单击“关注”和“关注者”来查看我关注的人和关注我的人,但我不确定为什么会有NPE吗... 我成功地可以关注用户,用户
我是 state Management 的新手,正在使用 provider package 。产生这些类型的异常有多少种不同的原因,我该如何解决,此异常是在 didChangeDependencies
我讨厌发布“这应该很容易,我错过了什么”问题,但是......这应该很容易,我错过了什么?我在这个测试代码上没有得到匹配,我不明白为什么。模式是(或应该是)“任何三个数字,后跟任何三个相同的数字,后跟
我正在研究 Chapter 11在 Hartl 的教程中,试图让用户 Controller 中的未登录用户访问关注者和关注页面通过。我遇到了一个错误,Rails 会提示未定义的 admin? 方法,尽
我是一名优秀的程序员,十分优秀!