- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
背景
我正在构建一个两层 C# .net 应用程序:
如果您想了解我正在构建的应用程序的更多详细信息,我给出的解释可能过于详尽了 here .
当前发展
目前,我正在开发 Winforms 客户端。特别是,我正在尝试在此客户端中充分实现命令模式。我有幸偶然发现this优秀的博客文章,概述了可靠的命令架构。为了补充该帖子,作者 followed up通过解释他如何将查询与命令分开。阅读这些博客后,很明显我的第 2 层(Web API 服务)将从实现这两个方面受益匪浅。通用实现具有出色的灵 active 、可测试性和可扩展性。
问题
我不太清楚的是我如何在 winforms 客户端(第 1 层)上实现这些模式。查询和命令在这里继续被认为是分开的吗?考虑一个基本操作,例如登录尝试。那是查询还是命令?最终,您需要从 Web 服务返回数据(服务器上的用户信息),所以这会让我认为这是一个查询。另一种情况呢,比如请求创建一个新用户。我知道您会创建一个命令对象来存储用户信息并将其发送到服务。命令应该是即发即弃的,但是您不想从服务那里得到命令成功的某种确认吗?此外,如果命令处理程序返回 void,您将如何告诉演示者用户创建请求是否成功?
归根结底,对于任何给定的 UI 任务(比如用户创建请求),最终是否会得到一个基于 winforms 客户端的查询/命令,以及一个 web api 服务版本的在那一端处理请求的命令/查询?
最佳答案
Do queries and commands continue to be considered separate here?
是的,通常您会触发一个命令,如果您需要在执行此操作后更新 UI,您将执行查询以获取新信息。举个例子可以清楚地说明这一点。
假设您要为某个区域分配一个特定的守卫。命令(只是一个 DTO )需要的唯一信息是 Id
guard 和Id
该地区的。相关CommandHandler
将执行所有任务来处理这个,例如将那个守卫从另一个区域移走,将他记为不可用等。
现在您的 UI 会想要显示更改。用户界面可能有某种列表,其中包含所有守卫及其分配的区域。此列表将由一个 GetActiveGuardsAndAreaQuery
填充。这将返回 List<GuardWithAreaInformationDto>
.这DTO
可能包含有关所有 guard 的各种信息。从命令返回此信息并不是完全分离关注点,因为原子命令处理可以很好地用于类似但略有不同的 UI,这将需要对 UI 信息进行略有不同的更新。
such as a login attempt. Is that a query or a command?
IMO 登录尝试都不是。这是一个横切关注点,是数据隐藏在安全连接后面的实现细节。然而,应用程序不应该关心这个细节。考虑与另一个客户一起使用该应用程序,您可以在其中托管 WebApi 服务 Active Directory
您可以使用的域 Windows Authentication
.在那种情况下,用户只需登录到他的机器,安全性由客户端和服务器操作系统在通信时处理。
使用您所指的模式可以使用 AuthenticateToWebApiServiceCommandHandlerDecorator
很好地完成此操作这通过以模态形式询问用户、从配置文件中读取它或其他任何方式来确保它们是服务于服务的登录凭据。
检查凭据是否有效可以通过执行一种标准 Query
来完成您的应用程序总是需要诸如 CheckIfUpdateIsAvailableQuery
.如果查询成功,则登录尝试成功,否则失败。
if a command handler returns void, how would you tell the presenter whether or not the user creation request was successful?
虽然看起来 void
不返回任何东西这不是真的。因为如果它没有因某些异常而失败(并明确显示出了什么问题!),它就一定成功了。
在 follow up 中在提到的博客文章中,@dotnetjunkie 描述了一种从命令返回信息的方法,但要注意文章顶部添加的评论。
总而言之,从失败的命令中抛出明确的异常。您可以添加一个额外的抽象客户端层来很好地处理这个问题。您可以注入(inject) IPromptableCommandHandler
,而不是直接将 commandhandler 注入(inject)到不同的演示者中。它在编译时只有一个开放的通用实现:
public interface IPromptableCommandHandler<TCommand>
{
void Handle(TCommand command, Action succesAction);
}
public class PromptableCommandHandler<TCommand> : IPromptableCommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> commandHandler;
public PromptableCommandHandler(ICommandHandler<TCommand> commandHandler)
{
this.commandHandler = commandHandler;
}
public void Handle(TCommand command, Action succesAction)
{
try
{
this.commandHandler.Handle(command);
succesAction.Invoke();
}
catch (Exception)
{
MessageBox.Show("An error occured, please try again.");
// possible other actions like logging
}
}
}
// use as:
public void SetGuardActive(Guid guardId)
{
this.promptableCommandHandler.Handle(new SetGuardActiveCommand(guardId),() =>
this.RefreshGuardsList());
}
At the end of the day, for any given UI task (say the user creation request), does it end up that you end up having a winforms client based query/command, as well as a web api service version of the command/query which handles the request on that end?
不!
客户端你应该创建一个单一的开放通用CommandHandlerProxy
唯一的任务是将命令 dto 传递给 WebApi 服务。
对于服务端架构,您应该阅读另一篇后续文章:Writing Highly Maintainable WCF Services它描述了一个服务器端架构来很好地处理这个问题。链接的项目还包含 WebApi 的实现!
关于c# - 如何在 WinForms 客户端应用程序中使用命令模式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38670725/
我需要将文本放在 中在一个 Div 中,在另一个 Div 中,在另一个 Div 中。所以这是它的样子: #document Change PIN
奇怪的事情发生了。 我有一个基本的 html 代码。 html,头部, body 。(因为我收到了一些反对票,这里是完整的代码) 这是我的CSS: html { backgroun
我正在尝试将 Assets 中的一组图像加载到 UICollectionview 中存在的 ImageView 中,但每当我运行应用程序时它都会显示错误。而且也没有显示图像。 我在ViewDidLoa
我需要根据带参数的 perl 脚本的输出更改一些环境变量。在 tcsh 中,我可以使用别名命令来评估 perl 脚本的输出。 tcsh: alias setsdk 'eval `/localhome/
我使用 Windows 身份验证创建了一个新的 Blazor(服务器端)应用程序,并使用 IIS Express 运行它。它将显示一条消息“Hello Domain\User!”来自右上方的以下 Ra
这是我的方法 void login(Event event);我想知道 Kotlin 中应该如何 最佳答案 在 Kotlin 中通配符运算符是 * 。它指示编译器它是未知的,但一旦知道,就不会有其他类
看下面的代码 for story in book if story.title.length < 140 - var story
我正在尝试用 C 语言学习字符串处理。我写了一个程序,它存储了一些音乐轨道,并帮助用户检查他/她想到的歌曲是否存在于存储的轨道中。这是通过要求用户输入一串字符来完成的。然后程序使用 strstr()
我正在学习 sscanf 并遇到如下格式字符串: sscanf("%[^:]:%[^*=]%*[*=]%n",a,b,&c); 我理解 %[^:] 部分意味着扫描直到遇到 ':' 并将其分配给 a。:
def char_check(x,y): if (str(x) in y or x.find(y) > -1) or (str(y) in x or y.find(x) > -1):
我有一种情况,我想将文本文件中的现有行包含到一个新 block 中。 line 1 line 2 line in block line 3 line 4 应该变成 line 1 line 2 line
我有一个新项目,我正在尝试设置 Django 调试工具栏。首先,我尝试了快速设置,它只涉及将 'debug_toolbar' 添加到我的已安装应用程序列表中。有了这个,当我转到我的根 URL 时,调试
在 Matlab 中,如果我有一个函数 f,例如签名是 f(a,b,c),我可以创建一个只有一个变量 b 的函数,它将使用固定的 a=a1 和 c=c1 调用 f: g = @(b) f(a1, b,
我不明白为什么 ForEach 中的元素之间有多余的垂直间距在 VStack 里面在 ScrollView 里面使用 GeometryReader 时渲染自定义水平分隔线。 Scrol
我想知道,是否有关于何时使用 session 和 cookie 的指南或最佳实践? 什么应该和什么不应该存储在其中?谢谢! 最佳答案 这些文档很好地了解了 session cookie 的安全问题以及
我在 scipy/numpy 中有一个 Nx3 矩阵,我想用它制作一个 3 维条形图,其中 X 轴和 Y 轴由矩阵的第一列和第二列的值、高度确定每个条形的 是矩阵中的第三列,条形的数量由 N 确定。
假设我用两种不同的方式初始化信号量 sem_init(&randomsem,0,1) sem_init(&randomsem,0,0) 现在, sem_wait(&randomsem) 在这两种情况下
我怀疑该值如何存储在“WORD”中,因为 PStr 包含实际输出。? 既然Pstr中存储的是小写到大写的字母,那么在printf中如何将其给出为“WORD”。有人可以吗?解释一下? #include
我有一个 3x3 数组: var my_array = [[0,1,2], [3,4,5], [6,7,8]]; 并想获得它的第一个 2
我意识到您可以使用如下方式轻松检查焦点: var hasFocus = true; $(window).blur(function(){ hasFocus = false; }); $(win
我是一名优秀的程序员,十分优秀!