使用 MVC 和 Ninject 作为 IoC 容器构建 WinForms 应用程序

2024-03-30

我必须重新编写一个大型 WinForms 应用程序,并且我想使用 MVC 来增强测试能力等。我还想采用 Ninject 作为我的 IoC 容器,因为它轻量、快速,并且会增加我的应用程序未来的可扩展性。

我进行了大量的阅读,并成功地开始了解这个新应用程序的架构。但是,我不确定使用 Ninject 时我的想法是否正确。代码...

从 Program.cs 和相关类开始...

static class Program
{
    [STAThread]
    static void Main()
    {
        FileLogHandler fileLogHandler = new FileLogHandler(Utils.GetLogFilePath());
        Log.LogHandler = fileLogHandler;
        Log.Trace("Program.Main(): Logging initialized");

        CompositionRoot.Initialize(new ApplicationModule());

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(CompositionRoot.Resolve<ApplicationShellView>());
    }
}

public class CompositionRoot
{
    private static IKernel _ninjectKernel;

    public static void Initialize(INinjectModule module)
    {
        _ninjectKernel = new StandardKernel(module);
    }

    public static T Resolve<T>()
    {
        return _ninjectKernel.Get<T>();
    }
}

public class ApplicationModule : NinjectModule
{
    public override void Load()
    {
        Bind(typeof(IApplicationShellView)).To(typeof(ApplicationShellView));
    }
}

An my ApplicationShellView is

public partial class ApplicationShellView : Form, IApplicationShellView
{
    public ApplicationShellView()
    {
        InitializeComponent();
    }

    public void InitializeView()
    {
        dockPanel.Theme = vS2012LightTheme;
    }
}

带接口

public interface IApplicationShellView
{
    void InitializeView();
}

该视图的控制器是

public class ApplicationShellController
{
    private IApplicationShellView view;

    public ApplicationShellController(IApplicationShellView view)
    {
        view.InitializeView();
    }
}

目前控制器是多余的,尽管此代码有效并且我的视图显示,但我有一些重要的问题......

  1. 我应该使用ApplicationShellController初始化我的表单,目前这是not使用MVC“模式”?
  2. 感觉就像我写了一个服务定位器,从我读到的内容来看,这很糟糕。我还应该如何使用 Ninject for IoC 来初始化我的应用程序?
  3. 关于我所做的正确[如果有的话!]/错误还有其他建议吗?

非常感谢你花时间陪伴。


  1. 不,你不应该初始化你的控制器,这正是 IoC 和 Ninject 的用途。当你初始化视图/表单时,Ninject 应该让视图获取它所依赖的控制器,这将自动获取它所依赖的控制器等等。
    当然,这不会像您现在设置的那样起作用。对于初学者来说,您的视图需要知道它所依赖的控制器。

    public partial class ApplicationShellView : Form, IApplicationShellView
    {
        private IApplicationShellController _controller;
    
        public ApplicationShellView()
        {
            InitializeComponent();
            init();
    
            //InitializeView()
        }
    
        private void init() {
            _controller = NinjectProgram.Kernel.Get<IApplicationShellController>();
            //Because your view knows the controller you can always pass himself as parameter or even use setter to inject
            //For example:  _controller.SetView1(this);
        }
    
        public void InitializeView()
        {
            dockPanel.Theme = vS2012LightTheme;
        }
    }
    
    public class ApplicationShellController : IApplicationShellController
    {
    
        //Implementes functionality for the MainForm.
    
        public ApplicationShellController()
        {
            //Also possible to add other controllers with DI
        }
    }
    
  2. 这确实看起来像一个服务定位器,只需初始化您的视图就足够了。

    public class NinjectProgram
    {
        //Gets the inject kernal for the program.
        public static IKernel Kernel { get; protected set; }
    }
    
    public class Program : NinjectProgram
    {
        [STAThread]
        private static void Main()
        {
            Kernel = new StandardKernel();
            Kernel.Load(new ApplicationModule());
    
            Application.Run(new ApplicationShellView());
        }
    }
    
    public class ApplicationModule : NinjectModule
    {
        public override void Load()
        {
            //Here is where we define what implementations map to what interfaces.
            Bind<IApplicationShellController>().To<ApplicationShellController>();
    
            //We can also load other modules this project depends on.
            Kernel.Load(new NinjectModule());
        }
    }
    
  3. 不要试图让它变得太复杂,一个好的开始很重要,但您可以在开发过程中随时随地根据需要应用更改。

我相信以下 GitHub 项目可能是一个很好的起点:如何在 WinForms 应用程序中使用 Ninject 的示例。 https://gist.github.com/dkellycollins/9c3fecaedd830094d7f2

如果您还有其他问题,请发表评论,我会尽快回答

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 MVC 和 Ninject 作为 IoC 容器构建 WinForms 应用程序 的相关文章

  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 是否允许将类模板类型参数键入相同的名称?

    这似乎可以在 MSVC 中按预期编译甚至工作 但它是合法的 C 代码吗 它是否能保证执行此处所期望的操作 即将模板类型导出到结构体的同名用户 template
  • C# 中四舍五入到偶数

    我没有看到 Math Round 的预期结果 return Math Round 99 96535789 2 MidpointRounding ToEven returning 99 97 据我了解 MidpointRounding ToE
  • 访问“if”语句之外的变量

    我怎样才能使insuranceCost以外可用if陈述 if this comboBox5 Text Third Party Fire and Theft double insuranceCost 1 在 if 语句之外定义它 double
  • 如何在 Asp.net Gridview 列中添加复选框单击事件

    我在 asp 中有一个 gridview 其中我添加了第一列作为复选框列 现在我想选择此列并获取该行的 id 值 但我不知道该怎么做 这是我的 Aspx 代码
  • Paradox 表 - Oledb 异常:外部表不是预期的格式

    我正在使用 Oledb 从 Paradox 表中读取一些数据 我遇到的问题是 当我将代码复制到控制台应用程序时 代码可以工作 但在 WinForms 中却不行 两者都以 x86 进行调试 我实际上只是复制代码 在 WinForms 应用程序
  • 存储过程上的 OdbcCommand - 输出参数上出现“未提供参数”错误

    我正在尝试执行存储过程 通过 ODBC 驱动程序针对 SQL Server 2005 但收到以下错误 过程或函数 GetNodeID 需要参数 ID 但未提供该参数 ID 是我的过程的 OUTPUT 参数 在存储过程中指定了一个输入 mac
  • Backbone-relational 无法实例化两个 RelationalModel 对象

    我正在尝试实现 BackboneRelational 并不断获得 无法实例化多个 Backbone RelationalModel 每种类型都有相同的 ID class App Models User extends Backbone Re
  • 我可以仅在少数情况下关闭模拟吗

    我有一个始终使用模拟的应用程序 但是 当用户以管理员身份登录时 一些操作需要他们写入服务器本身 现在 如果这些用户在实际服务器上没有权限 有些用户没有 则不会让他们写入 我想做的是关闭几个命令的模拟 有没有办法做这样的事情 using Ho
  • 手动将 ClientBase 集合类型从 Array[] 更改为 List<>

    我将自己的 WCF 代理与 Client Base 一起使用 我想做一些类似于 svc util 中的 ct 属性的操作 并告诉代理返回 List 集合类型 我不能使用 List 因为实体由 nhibernate 管理 所以我必须使用 IL
  • 允许使用什么类型的内容作为 C 预处理器宏的参数?

    老实说 我很了解 C 编程语言的语法 但对 C 预处理器的语法几乎一无所知 尽管我有时在编程实践中使用它 所以问题来了 假设我们有一个简单的宏 它扩展为空 define macro param 可以放入宏调用构造中的语法有哪些限制 调用宏时
  • 从事务范围调用 WCF 服务方法

    我有这样的代码 using TransactionScope scope TransactionScopeFactory CreateTransactionScope some methodes calls for which scope
  • 设计 Javascript 前端 <-> C++ 后端通信

    在我最近的将来 我将不得不制作一个具有 C 后端和 Web 前端的系统 要求 目前 我对此了解不多 我认为前端将触发数据传输 而不是后端 所以不需要类似 Comet 的东西 由于在该领域的经验可能很少 我非常感谢您对我所做的设计决策的评论
  • 如何使用收益返回和递归获得字母的每个组合?

    我有几个像这样的字符串列表 可能有几十个列表 1 A B C 2 1 2 3 3 D E F 这三个仅作为示例 用户可以从几十个具有不同数量元素的类似列表中进行选择 再举个例子 这对于用户来说也是一个完全有效的选择 25 empty 4 1
  • TPL 数据流块下游如何获取源生成的数据?

    我正在使用 TPL Dataflow 处理图像 我收到处理请求 从流中读取图像 应用多次转换 然后将生成的图像写入另一个流 Request gt Stream gt Image gt Image gt Stream 为此 我使用块 Buff
  • 如何设置 CMake 与 clang 交叉编译 Windows 上的 ARM 嵌入式系统?

    我正在尝试生成 Ninja makefile 以使用 Clang 为 ARM Cortex A5 CPU 交叉编译 C 项目 我为 CMake 创建了一个工具链文件 但似乎存在错误或缺少一些我无法找到的东西 当使用下面的工具链文件调用 CM
  • 启动画面后主窗口出现在其他窗口后面

    我有一个带有启动屏幕的 Windows 窗体应用程序 当我运行该应用程序时 启动屏幕显示正常 消失并加载应用程序的主窗体 但是 当我加载主窗体时 它出现在包含该应用程序的 Windows 资源管理器目录下 这是运行启动画面然后运行主窗体的代
  • c# 模拟 IFormFile CopyToAsync() 方法

    我正在对一个异步函数进行单元测试 该函数将 IFormFile 列表转换为我自己的任意数据库文件类列表 将文件数据转换为字节数组的方法是 internal async Task
  • 无法使 Polly 超时策略覆盖 HttpClient 默认超时

    我正在使用 Polly 重试策略 并且正如预期的那样 在重试过程中HttpClient达到 100 秒超时 我尝试了几种不同的方法来合并 Polly 超时策略 将超时移至每次重试而不是总计 但 100 秒超时仍然会触发 我读过大约 5 个
  • FindAsync 很慢,但是延迟加载很快

    在我的代码中 我曾经使用加载相关实体await FindAsync 希望我能更好地遵守 C 异步指南 var activeTemplate await exec DbContext FormTemplates FindAsync exec

随机推荐

  • JUnit5 测试未从“application-test.yml”加载属性

    我正在尝试为我的服务类编写单元测试 该服务类依赖于配置属性类 MyService java Service RequiredArgsConstructor public class MyService private final MyCon
  • jmeter-如何获取当前日期和时间(以秒为单位)

    我想计算当前时间 以秒为单位 并将其用作我的 jmeter 测试计划中的参数 默认情况下 时间以毫秒为单位 有人可以帮我吗 您可以使用 time 函数 http jmeter apache org usermanual functions
  • SQL 查询来计算不同值的数量

    x y A P A P B P B Q 你好 我需要一个查询来返回 x 的所有唯一值 有多少个不同的 y 因此 对于上述数据 它将返回 x count A 1 B 2 Thanks 使用 GROUP BY 和COUNT DISTINCT h
  • 使用 ndk-gdb 调试 Android 本机应用程序

    我正在尝试在 eclipse 中使用 ndk gdb 调试具有一些本机 c 代码的 android 应用程序 似乎 gdb 服务器从命令行成功启动并正在接受命令 但在 Eclipse 中却显示了这个错误 从设备获取文件时出错 com and
  • UCWA 或 UCMA API 是否支持 Skype for Business Online?

    我们正在尝试找出最新的UCWA https msdn microsoft com en us library office dn324971 v office 16 aspx or UCMA https msdn microsoft com
  • Elastic beanstalk需要python 3.5

    我最近使用最新的稳定版本的 python 3 5 创建了一个新的 python 程序 不幸的是 AWS EB 不提供 3 5 基础镜像 我一直在尝试配置 ebextensions获取图像来升级 python 发行版 这是第一个操作 我还没有
  • 插入 id(自动生成,仅列)

    如果我想在表中插入一行 而该表只包含一个具有自动生成 ID 的列 那么我的 SQL 语句 MS SQL 应该是什么样子 以下两个查询不起作用 INSERT INTO MyTable MyTableId VALUES Null or simp
  • 你能解释一下这个查询的逻辑吗

    我有一个查询 查找薪水第四高的老师的姓名 我不明白这部分 SELECT COUNT DISTINCT T2 salary FROM teacher as T2 WHERE T2 salary gt T1 salary 3 from SELE
  • PHP文件夹权限问题

    我正在尝试使用 PHP 创建一个文件夹 然后在其中创建另一个文件夹 如果这是我的目录结构 home site owner user1 现在 我使用创建文件夹 mkdir home site newdir 0777 user apache 目
  • Tkinter 标签文本在特定循环中重叠

    我正在使用 Python 和 Tkinter 开发一个 简单 搜索界面 这是我得到的一些示例代码 usr bin env python from tkinter import import os import csv import sys
  • 有没有办法捕获列表理解中的失误?

    基于简单的列表理解 yay i for i in a if a i nay i for i in a if not a i 我想知道是否有一种方法可以同时分配yay and nay一次值 即条件上的命中和未命中 看起来像这样的东西 yay
  • 了解 REST API - 什么是 Context 和 @Context?

    我最近学习了 Restful Web 服务教程 但无法理解什么是context是 有人可以解释一下它是什么以及什么吗 Context does JAX RS 提供 Context注解注入与 HTTP 请求上下文相关的 12 个对象实例 它们
  • 使用需要标头并提供内容的 REST 请求下载文件

    我正在使用带有 REST API 的 AngularJs 我不知道 REST API 我可以通过发送 REST 请求使用 API 存储数字对象 我也可以通过 GET 请求获取它 请求需要有一些特定的标头 我的目标是为用户提供 下载并另存为
  • 将 Laravel 5.4 升级到最新版本(5.7)

    我正在使用 PHP 版本 5 6 4 开发 Laravel 5 4 我的目标是将我的项目升级到 PHP 7 1 的 Laravel 5 7 现在我的问题是 我是否必须升级到 5 5 gt 5 6 gt 5 7 还是可以直接从 5 4 升级到
  • 为什么 TFS Power Tools 2013 安装不询问我是否要安装 PowerShell Cmdlet?

    我们有一个利用 TFS PowerShell 管理单元 Microsoft TeamFoundation PowerShell 的 PowerShell 脚本 在我的开发工作站上安装 TFS 2013 Power Tools 时 自定义安装
  • Pandas:分类列和每个类别的行插入

    我似乎无法实现插入缺少值的行 同时将一列作为分类 假设以下数据框 df 其中 B 列是分类的 类别应按 d b c a 的顺序出现 df pd DataFrame A i i i j k B pd Categorical d c b b a
  • ASP.Net 中线程敏捷性的含义是什么?

    我正在阅读一篇有关 HttpContext 和 CallContext 的文章并查看线程敏捷性 这是什么意思 这意味着 IIS 可以自由地使用多个线程来处理单个请求 尽管不是并行的 基本上 IIS 尝试异步执行 I O 操作 从而在操作期间
  • 如何遍历表单上的所有复选框?

    我有一个包含许多动态生成的复选框的表单 在运行时 我如何迭代它们中的每一个 以便获取它们的值和 ID foreach Control c in this Controls if c is CheckBox Do stuff here
  • 在 Android studio 中的自定义视图编辑器中显示正确的布局

    我在 Android Studio 中遇到布局预览的奇怪行为 我开发了一个扩展 AppCompatButton 的自定义视图 并且布局是运行时的预期布局 但是布局预览中的布局未正确显示 特别是 该按钮已显示 但没有从自定义属性设置背景颜色
  • 使用 MVC 和 Ninject 作为 IoC 容器构建 WinForms 应用程序

    我必须重新编写一个大型 WinForms 应用程序 并且我想使用 MVC 来增强测试能力等 我还想采用 Ninject 作为我的 IoC 容器 因为它轻量 快速 并且会增加我的应用程序未来的可扩展性 我进行了大量的阅读 并成功地开始了解这个