gpt4 book ai didi

.net - DI 在桌面应用程序中有意义吗?

转载 作者:行者123 更新时间:2023-12-04 10:52:09 27 4
gpt4 key购买 nike

我即将创建一个桌面应用程序(使用 .NET windows 窗体)

本质上,我想创建一个 n 层应用程序,但我也想要层之间的松散耦合。但是,我不太确定这是否是 Windows 窗体的好方法

现在我只是想知道使用任何 IoC(StructureMap、Ninject、Spring.Net)是否真的是一个明智的选择,我之前已经将它们用于 Asp.Net Web 应用程序,但现在让我怀疑的是windows 表单我的业务实体将在我浏览选项卡时持续存在,并且与 Web 表单或 mvc 应用程序不同,在 Web 表单或 mvc 应用程序中,需要为每个执行的新请求注入(inject)我的业务实体,我的意思是因为 Asp.Net page life cycle在哪里执行初始化并控制实例化。

这是一个长期的开发项目,它结合了维护跟踪、库存、工单和管理报告。我目前正在为其架构制定提案。

也许我误解了使用 IoC 的意义,所以请告诉我您认为什么是更好的选择?

任何观点将不胜感激。

最佳答案

你的问题很奇怪。您的问题意味着您会以不同于 Web 应用程序的方式为 Winforms 应用程序编写业务层,但是如果您正确应用分层,业务层应该完全独立于所使用的技术。因此,从这个意义上说,如果您将依赖注入(inject)模式应用于 Web 应用程序的业务层,那么您也应该将其应用于桌面应用程序的业务层。

我目前正在自己​​开发一个 Winforms 项目,并广泛使用依赖注入(inject)模式(和一个 IoC 容器)。对我来说,不存在是否应该使用 DI 的问题;它很自然地来自应用 SOLID原则。然而,您是否应该使用 IoC 容器是一个完全不同的问题,尽管对于我编写的应用程序类型和我使用的架构类型,我无法想象没有它的生活。

尽管桌面应用程序在本质上与 Web 应用程序非常不同,但我在这两种类型的应用程序上使用相同的模式。例如,我在 Windows 窗体类中使用构造函数注入(inject),这些窗体主要依赖于一些通用接口(interface),即:

  • IRepository<TEntity> (存储库模式)用于加载实体。
  • IQueryHandler<TQuery, TResult>用于执行各种复杂或自定义的查询。
  • ICommandHandler<TCommand>用于执行用例(处理用户操作)。

  • 我在我构建的 Web 应用程序中使用相同的抽象。

    几个月前,这些接口(interface)帮助我将此桌面应用程序从 2 层应用程序(所有业务逻辑在桌面应用程序中运行)更改为 3 层应用程序(其中所有业务逻辑现在都移至 WCF 服务)。我们能够做到这一点,而无需更改表单中的任何代码。

    在 2 层模型中,我们没有注入(inject) ICommandHandler<TCommand>直接实现,但注入(inject)了一个(单例)代理类,每次调用时都会创建一个新的实现。例如,当表单调用注入(inject)的 ICommandHandler<ProcessOrder> 时,实际 CommandHandlerProxy<ProcessOrder>将启动生命周期范围(模仿 Web 应用程序的每个请求生活方式的生活方式)并创建真正的 ProcessOrderCommandHandler将执行实际逻辑的类。通过这样做,我们确保了一个单一的工作单元(在我们的例子中是 Entity Framework 的 DbContext)将被注入(inject)到这个“请求”中的所有类中。当然,在调用图的整个过程中都使用依赖注入(inject)。

    在新的 3 层模型中,表单注入(inject)了 WcfProxyCommandHandler<TCommand>它将给定的命令序列化为 JSON 并将其发送到 WCF 服务,该服务将接收它,反序列化命令,创建 ProcessOrderCommandHandler并执行命令。

    但请记住,此模型可能与您可能习惯使用的模型大不相同。例如:
  • 真正的实体隐藏在 WCF 服务后面。桌面应用程序对它们一无所知。
  • 而是 DTO当通过 IQueryHandler<TQuery, TResult> 请求数据时,从 WCF 服务返回 s抽象。
  • 我们使用 Entity Framework 5(带有 T4 和设计器的 POCO 类)。
  • 这些 DTO(主要)用于阅读;它们不会被发送回服务器进行更新。
  • 任何状态更改请求(用例的执行)都是通​​过向服务器发送命令消息(通过 ICommandHandler<TCommand> 抽象)来完成的。
  • 一个单独的用例封装在实现 ICommandHandler<TCommand> 的单个类中。界面。

  • 正如我所说,它一直是依赖注入(inject),这和所描述的设计给了我们很大的灵活性。例如:
  • 我们发现添加新功能非常容易。
  • 我们发现添加新的横切关注点非常容易。
  • 它降低了心理障碍;它使应用程序更易于维护,并且不太可能以意外方式中断。

  • 然而,我在这个过程中发现了一件事:
  • winforms 中的绑定(bind)已优化为与数据集一起使用。如果您尝试其他任何东西(Poco 的、 Entity Framework 实体等),您会遇到一些非常令人沮丧的时刻,您会发现对除 DataSet 之外的任何其他东西的支持都很小。很明显,微软没有在这个领域投资,也不会再投资这个领域。为了解决这些限制,我们编写了自己的 BindingList<T>实现,发现很难创建一个能够正确处理排序和过滤的实现(特别是因为我们的 DTO 没有实现 INotifyPropertyChanged)。我们也wrote our own infrastructure向 Winforms 添加 DataAnnotations 验证支持。

  • 如果您想了解更多关于我使用的设计的信息,请阅读以下文章:
  • Meanwhile... on the command side of my architecture
  • Meanwhile... on the query side of my architecture
  • Writing Highly Maintainable WCF Services
  • 关于.net - DI 在桌面应用程序中有意义吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19937187/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com