背景
我正在构建一个双层应用程序:
Winforms客户端将使用WebAPI服务HttpClient.两层都大量使用IoC和依赖注入设计模式
题
当Winforms应用程序需要来自WebAPI服务的数据时,演示者将协调请求.我的问题是,你会HttpClient直接在演示者内部使用吗?为了保持演示者的可测试性,您如何确保不必依赖具体的HttpClient电话?我想在某种程度上也整合了这个问题的最佳答案.
c# design-patterns winforms asp.net-web-api dotnet-httpclient
背景
我正在构建一个双层C#.net应用程序:
目前,我对Winforms客户端应用程序的整体架构有疑问.我是编程新手(大约一年),但我在这个应用程序方面取得了很大的进步.我想退后一步,重新评估我目前的做法,检查我是否正朝着正确的方向前进.
应用领域
Winforms应用程序是一个相当简单的安全人员跟踪应用程序.主视图(表单)是应用程序的焦点,并且具有将内容分组为功能区域的不同部分(例如,用于跟踪人员日程表的部分,用于跟踪分配到何处的人员的部分等).应用程序侧面的菜单启动辅助视图(例如历史记录,统计信息,联系人等).这个想法是安全办公室可以使用该应用程序来组织日常操作,然后保留数据库中所有内容的详细历史记录,以便将来进行报告.
技术细节
如上所述,Winforms客户端是使用MVP模式(被动视图)构建的,重点是尽可能多地使用依赖注入(通过SimpleInjector IoC容器).每个视图(表单)都与一个演示者配对.视图实现接口,允许演示者控制视图(无论具体实现如何).该视图会引发演示者订阅的事件.目前,不允许演示者直接与另一位演示者通信.
应用程序控制器用于协调应用程序.这是我的应用程序架构的领域,我是最不明智的(因此是帖子标题).应用程序控制器目前用于:
在应用程序启动时,IoC容器已注册到应用程序控制器中.例如,这允许应用程序控制器从容器创建演示者,然后由容器自动处理所有后续依赖项(视图,服务等).
题
为了使所有演示者都可以访问Application Controller,我将控制器创建为静态类.
public static class ApplicationController
{
private static Session _session;
private static INavigationWorkflow _workflow;
private static EventAggregator _aggregator;
#region Registrations
public static void RegisterSession(Session session) {}
public static void RegisterWorkflow(INavigationWorkflow workflow) {}
public static void RegisterAggregator(EventAggregator aggregator) {}
#endregion
#region Properties
public static Session Session
{
get { return _session; }
}
#endregion
#region Navigation
public static void NavigateToView(Constants.View view) …Run Code Online (Sandbox Code Playgroud) 背景
我正在构建一个两层的 C# .net 应用程序:
如果您想了解我正在构建的应用程序的更多详细信息,我在这里给出的解释可能过于彻底。
当前发展
目前,我正在 Winforms 客户端上工作。特别是,我正在尝试在此客户端中散列命令模式的适当实现。我有幸偶然发现了这篇出色的博客文章,其中概述了一个可靠的命令架构。为了补充那篇文章,作者接着解释了他如何将查询与命令分开。阅读这些博客后,很明显我的第 2 层(Web api 服务)将从实现这两个中受益匪浅。通用实现允许极好的灵活性、可测试性和可扩展性。
题
我不太清楚的是我如何在 winforms 客户端(第 1 层)上实现这些模式。此处是否继续将查询和命令视为分开的?考虑一个基本操作,例如登录尝试。这是查询还是命令?最终,您需要从 Web 服务返回数据(服务器上的用户信息),因此我认为这是一个查询。另一种情况如何,例如创建新用户的请求。我知道您将创建一个命令对象来存储用户信息并将其发送给服务。命令应该是即发即忘,但您是否不想从服务中获得某种命令是否成功的确认?此外,如果命令处理程序返回 void,
归根结底,对于任何给定的 UI 任务(比如用户创建请求),是否最终会得到一个基于 winforms 客户端的查询/命令,以及命令/查询的 web api 服务版本哪个处理那方面的请求?
背景
我正在构建一个winforms应用程序,我正在使用IoC容器(SimpleInjector)来注册我的类型.在我的应用程序中,大多数屏幕(即表单)在任何给定时间只有一个实例.
问题
对于在任何给定时间只需要一个实例的表单,我可以将它们注册为单例:
container.Register<IHomeView, HomeView>(Lifestyle.Singleton);
Run Code Online (Sandbox Code Playgroud)
这允许我使用容器来跟踪所有表单.但是,在这种情况下,当表单被关闭时,它将被释放(表单实现IDisposable).如果应用程序尝试使用容器再次打开该表单,则将处置该表单的容器实例,并抛出异常.
题
处理这个问题的正确方法是什么?我目前看到两种解决方案:
我可以通过在验证期间抑制诊断警告来解决问题b).
registration = container.GetRegistration(typeof(ILoginView)).Registration;
registration.SuppressDiagnosticWarning(
DiagnosticType.DisposableTransientComponent,
"Winforms registration supression.");
Run Code Online (Sandbox Code Playgroud)
在这里采取正确的方法是什么?我错过了什么吗?
我正在使用 Angular 7,我有一个带有Angular Material Table的简单组件。通过某些事件,例如单击鼠标,我希望能够更新该现有表的数据和表头。
前:
之后(目标):
目前,我正在获取数据更新。但是,我无法更新列的标题文本,除非我做了一个相当糟糕的窗口超时调用。
这很难描述,因此stackblitz 存储库应该会有所帮助。在我链接到那里的“table-dynamic-columns.example.ts”文件中,我在“changeColumnHeader”按钮单击处理程序上尝试了两种不同的策略。看来,为了让我的新列标题显示出来,我需要先清除表中显示的列,然后在超时后将它们正确设置回来。也许它不起作用,因为属性名称保持不变(即“id”)并且只有标题发生了变化。
有谁知道更好的方法来让它正确更新?
使用Angular Material Table组件,默认情况下,表格上的列标题将左对齐,这很好:
但是,如果标题没有足够的空间,则文本会换行,这很好,只是文本然后居中对齐...
如何使文本左对齐?我认为这会很简单,但我遇到了问题。这似乎也只发生在带有排序的标题上,因为如果您mat-sort-header从任何标题单元格中删除指令,则左对齐正确。
我尝试添加以下 css 类定义,但没有运气:
.mat-sort-header-button {
text-align: left;
}
Run Code Online (Sandbox Code Playgroud)
我已经从VS模板创建了一个ASP.NET Core Web API应用程序(我使用最新的ASP.NET Core RC2更新了VS).但是,在尝试设置我的应用程序以使用SimpleInjector作为IoC容器时,我遇到了问题.
我正在使用此处提供的说明.当我镜像在该链接上找到的指令时,我在ConfigureServices方法中收到错误,指出IServiceCollection没有AddInstance的定义.它还说无法找到IControllerActivator.
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddMvc();
services.AddInstance<IControllerActivator>(
new SimpleInjectorControllerActivator(container));
services.AddInstance<IViewComponentInvokerFactory>(
new SimpleInjectorViewComponentInvokerFactory(container));
}
Run Code Online (Sandbox Code Playgroud)
我意识到可能存在一些问题,因为我使用的是最新的ASP.NET版本(并且SimpleInjector对ASP.NET Core的支持是测试版),但我很好奇是否有人知道一种解决方法.谢谢!
正如标题所述,我很好奇是否可以从 转换Task<List<Derived>>为Task<List<BaseType>>?
我有几个返回 的方法Task<List<Derived>>,并且可以有多种类型的派生类。我想将所有任务存储在任务列表中:List<Task<List<BaseType>>>稍后执行。
如果我的任务不是包装列表,这将非常简单:链接
编辑1
这是我遇到问题的部分,我在将任务存储在列表中时遇到问题:
// This throws an error (cannot convert derived list to base list)
var tasks = new List<Task<List<BaseType>>>
{
asyncThing1(), // returns Task<List<Derived1>>
asyncThing2(), // returns Task<List<Derived2>>
// ... n number more
};
// Need the list of tasks before I can execute
List<BaseType>[] results = await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)
编辑2
以上,List<Base>[]改为List<BaseType>[]
c# ×6
winforms ×4
.net ×3
angular ×2
typescript ×2
asp.net ×1
async-await ×1
asynchronous ×1
css ×1
generics ×1
sass ×1