在C#中使用WinForms上的Microsoft扩展依赖注入

时间:2017-11-27 17:14:08

标签: c# winforms dependency-injection

我对DI的了解非常有限。 我正在一个解决方案中开发一个WinForm项目,解决方案中的其他任何地方都使用了Microsoft Extension Dependency Injection

我需要将一些依赖项传递给MainForm的构造函数:

public partial class MainForm : Form
{
   public MainForm(ISomeThing someThing)
   {
   }
}

在Main方法中,MainForm的一个实例传递给Run方法:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new MainForm());
}

我尝试使用DI通过提供服务提供程序来实例化Mainform的实例:

private static IServiceProvider ServiceProvider { get; set; }

然后按如下方式为其分配一个对象:

static void ConfigureServices()
{
   var services = new ServiceCollection();
   services.AddTransient<ISomeThing, SomeThing>();
   ServiceProvider = services.BuildServiceProvider();
}

然后在ConfigureServices()中拨打Main(),如下所示:

static void Main()
{
   Application.EnableVisualStyles();
   Application.SetCompatibleTextRenderingDefault(false);
   ConfigureServices();
   Application.Run(ServiceProvider.GetService(MainForm));
}

但是,我收到编译错误:“ MainForm是一种类型,在给定的上下文中无效

我发现以下链接使用SimpleInjectorUnity使用类似方法 但我不知道如何使用这种DI?或者我必须使用其他DI?

由于

4 个答案:

答案 0 :(得分:2)

您正在尝试获取与该类对应的typeof()实例。

这是GetService(typeof(MainForm)) 关键字的作用:

Form

请注意,您还需要将结果转换为int sc=-1; while (strings[sc++]!=0) { _asm{ PUSH SI; MOV SI,sc; get pointer MOV DL,strings[SI]; get character CMP DL,' '; if not space JNE next MOV AH,2H; display new line MOV DL,10H; what is significance of this line? INT 21H; And this one MOV DL,13H ; what is significane of this line next: MOV AH,2H; display character INT 21H; POP SI; } }

答案 1 :(得分:1)

我将对其进行如下修改。

您不需要使用参数将任何东西传递给MainForm的构造函数。

在Program类中,Something的一个实例注册为ISomething的实现者,但Application.Run()保持不变,

using Microsoft.Extensions.DependencyInjection;  // provides DI
using SomeThing; // implements ISomeThing interface and SomeThing class 

/*Program.cs */ 
public static class Program
{
  //..
  public static IServiceProvider ServiceProvider { get; set; }

  static void ConfigureServices()
  {
    var services = new ServiceCollection();
    services.AddTransient<ISomeThing, SomeThing>();
    ServiceProvider = services.BuildServiceProvider();
  }

  [STAThread]
  static void Main()
  {  
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    ConfigureServices();
    Application.Run(new MainForm());
  }
}

现在在MainForm中,构造函数将查询已注册的依赖项并将其保存为私有属性,例如

    public class MainForm: Form
    {

      // ..

       private readonly IMySomeThing _mySomething;

       public MainForm()
       {
        _mySomething =   (IMySomeThing)Program.ServiceProvider.GetService(typeof(IMySomeThing));
       }     

    }

MainForm ctor完成后,可以在MainForm中的任何位置访问(或可以调用)私有字段_mySomething。哪个类实现IMySomething由与ServiceProvider的注册控制。这样可以通过替换某些拥有的类来更改类的行为。

我使用DI来简化某些单元测试。例如,在单元测试中,可以通过简单的true / false返回替代项来替换实现某些复杂子任务的依赖项。该测试方法通常称为“模拟”。它允许对中级和高级过程进行单元测试。

答案 2 :(得分:1)

我在我的代码中添加了一个辅助函数以使其更具可读性:

public static T? GetService<T>() where T : class
{
   return (T?)ServiceProvider.GetService(typeof(T));
}



//was:
// thing = (iThing)Program.ServiceProvider.GetService(typeof(iThing));

//now:
thing = Program.GetService<iThing>();


答案 3 :(得分:0)

这是最好的答案

Application.Run(new MainForm((ISomeThing)ServiceProvider.GetService(typeof(ISomeThing))));