小编And*_*rew的帖子

从MVP Winform Client使用WebAPI的设计模式

背景

我正在构建一个双层应用程序:

  • 第1层:使用MVP(Model-View-Presenter)设计模式Winforms应用程序.
  • 第2层:WebAPI RESTful服务.

Winforms客户端将使用WebAPI服务HttpClient.两层都大量使用IoC和依赖注入设计模式

当Winforms应用程序需要来自WebAPI服务的数据时,演示者将协调请求.我的问题是,你会HttpClient直接在演示者内部使用吗?为了保持演示者的可测试性,您如何确保不必依赖具体的HttpClient电话?我想在某种程度上也整合了这个问题的最佳答案.

c# design-patterns winforms asp.net-web-api dotnet-httpclient

5
推荐指数
1
解决办法
1414
查看次数

Winforms - MVP模式:使用静态ApplicationController来协调应用程序?

背景

我正在构建一个双层C#.net应用程序:

  1. 第1层:使用MVP(Model-View-Presenter)设计模式Winforms客户端应用程序.
  2. 第2层:位于Entity Framework和SQL Server之上的WebAPI RESTful服务.

目前,我对Winforms客户端应用程序的整体架构有疑问.我是编程新手(大约一年),但我在这个应用程序方面取得了很大的进步.我想退后一步,重新评估我目前的做法,检查我是否正朝着正确的方向前进.

应用领域

Winforms应用程序是一个相当简单的安全人员跟踪应用程序.主视图(表单)是应用程序的焦点,并且具有将内容分组为功能区域的不同部分(例如,用于跟踪人员日程表的部分,用于跟踪分配到何处的人员的部分等).应用程序侧面的菜单启动辅助视图(例如历史记录,统计信息,联系人等).这个想法是安全办公室可以使用该应用程序来组织日常操作,然后保留数据库中所有内容的详细历史记录,以便将来进行报告.

技术细节

如上所述,Winforms客户端是使用MVP模式(被动视图)构建的,重点是尽可能多地使用依赖注入(通过SimpleInjector IoC容器).每个视图(表单)都与一个演示者配对.视图实现接口,允许演示者控制视图(无论具体实现如何).该视图会引发演示者订阅的事件.目前,不允许演示者直接与另一位演示者通信.

应用程序控制器用于协调应用程序.这是我的应用程序架构的领域,我是最不明智的(因此是帖子标题).应用程序控制器目前用于:

  1. 打开新视图(表单)并管理打开的表单.
  2. 通过事件聚合器促进应用程序组件之间的通信.一位演示者发布一个事件,任何数量的演示者都可以订阅该事件.
  3. 主机会话信息(即安全上下文/登录,配置数据等)

在应用程序启动时,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)

.net c# dependency-injection winforms simple-injector

5
推荐指数
1
解决办法
1390
查看次数

如何在 WinForms 客户端应用程序中使用命令模式?

背景

我正在构建一个两层的 C# .net 应用程序:

  1. 第 1 层:使用 MVP(模型-视图-演示者)设计模式的 Winforms 客户端应用程序。
  2. 第 2 层:位于实体框架和 SQL Server 之上的 WebAPI RESTful 服务。

如果您想了解我正在构建的应用程序的更多详细信息,我在这里给出的解释可能过于彻底。

当前发展

目前,我正在 Winforms 客户端上工作。特别是,我正在尝试在此客户端中散列命令模式的适当实现。我有幸偶然发现了这篇出色的博客文章,其中概述了一个可靠的命令架构。为了补充那篇文章,作者接着解释了他如何将查询与命令分开。阅读这些博客后,很明显我的第 2 层(Web api 服务)将从实现这两个中受益匪浅。通用实现允许极好的灵活性、可测试性和可扩展性。

我不太清楚的是我如何在 winforms 客户端(第 1 层)上实现这些模式。此处是否继续将查询和命令视为分开的?考虑一个基本操作,例如登录尝试。这是查询还是命令?最终,您需要从 Web 服务返回数据(服务器上的用户信息),因此我认为这是一个查询。另一种情况如何,例如创建新用户的请求。我知道您将创建一个命令对象来存储用户信息并将其发送给服务。命令应该是即发即忘,但您是否不想从服务中获得某种命令是否成功的确认?此外,如果命令处理程序返回 void,

归根结底,对于任何给定的 UI 任务(比如用户创建请求),是否最终会得到一个基于 winforms 客户端的查询/命令,以及命令/查询的 web api 服务版本哪个处理那方面的请求?

.net c# winforms simple-injector asp.net-web-api

5
推荐指数
1
解决办法
2006
查看次数

Winforms:如何使用IoC容器注册表单

背景

我正在构建一个winforms应用程序,我正在使用IoC容器(SimpleInjector)来注册我的类型.在我的应用程序中,大多数屏幕(即表单)在任何给定时间只有一个实例.

问题

对于在任何给定时间只需要一个实例的表单,我可以将它们注册为单例:

container.Register<IHomeView, HomeView>(Lifestyle.Singleton);
Run Code Online (Sandbox Code Playgroud)

这允许我使用容器来跟踪所有表单.但是,在这种情况下,当表单被关闭时,它将被释放(表单实现IDisposable).如果应用程序尝试使用容器再次打开该表单,则将处置该表单的容器实例,并抛出异常.

处理这个问题的正确方法是什么?我目前看到两种解决方案:

  1. 对于每个表单,覆盖表单接近隐藏表单,而不是实际关闭它.我真的不喜欢这个主意.我觉得我每次都要关闭表格,然后从一个新的/新的表格开始.
  2. 使用短暂的生活方式注册表单而不是单身.在这种情况下,容器实际上更像是一个工厂.我遇到两个问题:a)我失去了通过容器跟踪表单的能力,并且,b)容器在验证期间抛出异常,说一次性类型不应该被注册为瞬态(我不明白为什么这是).这些问题都适用于我同时需要多个实例的表单.

我可以通过在验证期间抑制诊断警告来解决问题b).

registration = container.GetRegistration(typeof(ILoginView)).Registration;
registration.SuppressDiagnosticWarning(
    DiagnosticType.DisposableTransientComponent,
    "Winforms registration supression.");
Run Code Online (Sandbox Code Playgroud)

在这里采取正确的方法是什么?我错过了什么吗?

.net c# inversion-of-control winforms simple-injector

4
推荐指数
1
解决办法
4045
查看次数

角度材料表 - 如何更新现有表的列标题?

我正在使用 Angular 7,我有一个带有Angular Material Table的简单组件。通过某些事件,例如单击鼠标,我希望能够更新该现有表的数据和表头。

前:

在此处输入图片说明

之后(目标):

在此处输入图片说明

目前,我正在获取数据更新。但是,我无法更新列的标题文本,除非我做了一个相当糟糕的窗口超时调用。

这很难描述,因此stackblitz 存储库应该会有所帮助。在我链接到那里的“table-dynamic-columns.example.ts”文件中,我在“changeColumnHeader”按钮单击处理程序上尝试了两种不同的策略。看来,为了让我的新列标题显示出来,我需要先清除表中显示的列,然后在超时后将它们正确设置回来。也许它不起作用,因为属性名称保持不变(即“id”)并且只有标题发生了变化。

有谁知道更好的方法来让它正确更新?

typescript angular-material angular angular-material-table

4
推荐指数
1
解决办法
3550
查看次数

Angular Material Table - CSS 用于在文本换行时使标题左对齐

使用Angular Material Table组件,默认情况下,表格上的列标题将左对齐,这很好:

左对齐标题

但是,如果标题没有足够的空间,则文本会换行,这很好,只是文本然后居中对齐...

居中对齐文本

如何使文本左对齐?我认为这会很简单,但我遇到了问题。这似乎也只发生在带有排序的标题上,因为如果您mat-sort-header从任何标题单元格中删除指令,则左对齐正确。

我尝试添加以下 css 类定义,但没有运气:

.mat-sort-header-button {
    text-align: left;
}
Run Code Online (Sandbox Code Playgroud)

这是我正在玩的演示

css sass typescript angular-material angular

2
推荐指数
1
解决办法
1086
查看次数

带有简单注入器的ASP.NET核心

我已经从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的支持是测试版),但我很好奇是否有人知道一种解决方法.谢谢!

c# asp.net simple-injector asp.net-web-api

1
推荐指数
1
解决办法
4944
查看次数

如何从 Task&lt;List&lt;Derived&gt;&gt; 转换为 Task&lt;List&lt;Base&gt;&gt;

正如标题所述,我很好奇是否可以从 转换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# generics asynchronous async-await

-1
推荐指数
1
解决办法
930
查看次数