Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在下游生成新的Windows窗体时如何使用DI?_C#_Winforms_Dependency Injection_Unity Container - Fatal编程技术网

C# 在下游生成新的Windows窗体时如何使用DI?

C# 在下游生成新的Windows窗体时如何使用DI?,c#,winforms,dependency-injection,unity-container,C#,Winforms,Dependency Injection,Unity Container,我的Unity DI容器最初用于我的Windows窗体应用程序。在Program.cs中,我有以下内容: static void Main() { var container = BuildUnityContainer(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(container.Resolve

我的Unity DI容器最初用于我的Windows窗体应用程序。在
Program.cs
中,我有以下内容:

static void Main()
{
    var container = BuildUnityContainer();
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(container.Resolve<MainForm>());
}

private static IUnityContainer BuildUnityContainer()
{
    var container = new UnityContainer();
    container.RegisterType<ITest, MyTestClass>();
    container.RegisterType<ISomeOtherTest, MyOtherClass>();
    return container;
}
容器已解析,代码工作正常。问题是,如何从
MainForm
实例化具有以下构造函数的新表单,比如
Form2

private readonly ISomeOtherTest someOtherTest;

    public Form2(ISomeOtherTest someOtherTest)
    {
       this.someOtherTest = someOtherTest;
       InitializeComponent();
    }
如果我在我的
main表单中尝试以下操作

Form2 form2 = new Form2();
form2.Show();
它会崩溃,抱怨我没有向构造函数提供值。然而,我已经解决了我的容器,我认为所有下游容器都将得到解决。显然,我在这里遗漏了一些东西,因为它不起作用


这是否意味着我必须将所有依赖项预先加载到
MainForm
,即使该表单不使用它,这样我就可以将它们传递给我创建的任何新表单实例化?如果我有50个依赖项需要解决,并且让顶级表单的构造函数将它们全部解决,那么这个问题就很奇怪了。请帮助我澄清我的理解,因为我几乎只在Web API和MVC中使用了Unity和DI容器,而MVC已经为控制器内置了DI解析器,所以我必须在这里遗漏一些内容和理解。

您应该像这样创建表单

Form2 form = container.Resolve<Form2>();

DI与ASP.NET配合得很好,因为对象创建是通过管道委派的,他们将自己放在那里。在WinForm/WPF中,大多数情况下需要通过容器创建该类型。另外,如果你需要更多的帮助,你至少应该告诉你正在使用的DI(Unity,Ninject等)@SimonBelanger-请阅读我帖子中的第四个词:“我有Unity DI…”,我在最后一段中再次声明:“我使用了Unity…”你读得太快了,在这里,提供例子而不是抽象的描述更有用。@atconway,这是一个很好的问题。我自己也在努力解决同样的问题。我如何访问我的
MainForm
中的
container
变量?这只是在
Program.cs
中本地声明的,我在Intellisense中看不到它。我应该把它传给别人吗?@atconway:Declare
container
为public.@atconway你知道,我自己也不确定。我也有同样的问题。但是,我想了一下,读了马克·西曼关于stackoverflow的一些回答。我更新了我的答案,提出了如何做到这一点的想法。在这种情况下,您不需要自己创建工厂。MainForm解析将自动将工厂注入MainForm。我相信这就是composition root的想法(对容器的单个解析调用)。@atconway是的,这些都是好问题。我认为在某些时候,您需要确定什么是合理的,以及它如何影响关注点和测试的分离。你在测试你的表格吗?或者您正在测试您的业务逻辑?但我同意你的观点,我不知道构图根理论是如何处理这种情况的。另外,我正在编写一个模块化应用程序,在我的例子中,至少每个模块都需要与容器交互。如果您的所有表单都需要1-2个依赖项,那么一个想法可能是注入这些依赖项,并在MainForm中使用这些依赖项在MainForm中调用newctor@MEMarkFormFactory可以将接口返回到表单。。这可能会允许您模拟该表单(和工厂)并独立测试父表单和子表单?我认为区别在于,如果您正在测试这些类中的一个,您想通过容器传递它吗?还是模板厂?哪个更好?我认为是后者
Form2 form = container.Resolve<Form2>();
public class Form2Factory : IForm2Factory
{
    private readonly ISomeOtherTest someOtherTest;

    public Form2Factory(ISomeOtherTest someOtherTest)
    {
        this.someOtherTest = someOtherTest;
    }

    public Form2 Create()
    {
        return new Form2(someOtherTest);
    }
}


public class MainForm
{
    private readonly IForm2Factory form2Factory;

    public MainForm(IForm2Factory form2Factory)
    {
        this.form2Factory = form2Factory;
    }

    private void DoingSomething()
    {
        Form2 form = form2Factory.Create();
        form.Show();
    }
}