如何使用依赖注入多次创建对象

Posted

技术标签:

【中文标题】如何使用依赖注入多次创建对象【英文标题】:How to create object more than once with dependency injection 【发布时间】:2013-05-16 07:30:02 【问题描述】:

我使用的是 C#.Net,但任何相关示例都可以接受。

我有 2 个 winform,比如说 ListFrm 和 DetailFrm,其中每次用户单击 DetailFrm 中的按钮时,都会弹出一个新的 ListFrm,以便用户可以更改所选项目。

DetailFrm.cs

public class DetailFrm

    private readonly ListFrm _listFrm;

    public DetailFrm(ListFrm listFrm)
    
        _listFrm = listFrm;
    

    private SelectButton OnClick(object sender, EventArgs e)
    
        using(listFrm)
        
            listFrm.ShowDialog();

            // Do detail data filling here
        
    

ListFrm.cs

public class ListFrm

    public Item SelectedItem  get; set; 

    private readonly ListRepository _listRepository;

    public ListFrm(ListRepository listRepository)
    
        _listRepository = listRepository;
    

    private ListFrm_Load(object sender, EventArgs e)
    
        List<Item> listItem = _listRepository.GetAll();

        // Do adding to datagridview
    

    private dataGridViewSelect_CellDoubleClick(object sender, EventArgs e)
    
        SelectedItem = // Selected in datagridview

        this.Dispose;
    

我的问题是当我第二次点击 DetailFrm 的浏览按钮时,ListFrm 无法加载,因为它已经被处理掉了。

如何使用依赖注入来做到这一点?我无法创建 ListFrmFactory,因为它无法创建需要 ItemRepository 依赖项的新 ListFrm。

我也不想到处传递 DIContainer,因为它会是一个服务定位器。

如果在没有依赖注入的情况下完成,我会在每次需要时调用new ListFrm()

谢谢!

【问题讨论】:

为什么要处理表单? 你为什么要这样处理ListFrm实例? 好吧,选择第二次实际上并不是必需的情况,而只是为了适应这种可能性。而且我认为不再需要时无需维护资源消耗形式。我应该隐藏它吗? 【参考方案1】:

您可以使用委托注入来处理这种情况。这将使您能够将 Container 配置保存在一个位置,并在每次需要时创建一个新实例。

public class DetailFrm

    private readonly Func<ListFrm> _listFrmInstance;

    public DetailFrm(Func<ListFrm> listFrmInstance)
    
        _listFrmInstance = listFrmInstance;
    

    private SelectButton OnClick(object sender, EventArgs e)
    
        using(var listFrm = _listFrmInstance())
        
            listFrm.ShowDialog();

            // Do detail data filling here
        
    

【讨论】:

【参考方案2】:

我不知道你要做什么, 在这里你只需要关闭你的列表表单而不是处理它, 您的详细信息表单中只有一个实例,因此当您处理它时,下次无法使用它, 如果你想在你的表单类之间建立松散耦合的依赖关系,你应该定义一个接口,你的 listForm 应该实现它,并且在你的 detailForm 中,你必须有一个 listForm 的实例,类型为你的接口以获取更多信息,你可以看看这篇文章来自 MSDN: Dependancy Injection

【讨论】:

好吧,我想这是我的缺陷。那么,如果我处置了 DetailFrm,ListFrm 也会被处置吗?因为我不喜欢占用不应该存在的内存资源的想法。 当然它也会dispose,当GC迭代抛出对象时,当它发现没有人指向的东西时,它会从内存中删除它。 另一方面,您可以覆盖您的 detailForm 的 dispose 方法并手动调用您的 listForm dispose 方法,但是它有一些技巧来覆盖 win Form 的 dispose 方法,因为设计师之前已经覆盖了它,如何我们可以覆盖 win 表单的 dispose 方法吗?您可以阅读这篇文章:***.com/questions/1052147/…【参考方案3】:

不要丢弃表单。把它藏起来!

使用这个方法:

http://msdn.microsoft.com/en-us/library/system.windows.forms.control.hide.aspx

通知Form继承自Control

【讨论】:

【参考方案4】:

与其注入 ListFrm,不如注入一个 ListFrmFactory。让 ListFrmFactory 将 ListRepository 作为注入依赖项。然后你的工厂当然可以在需要时构建一个新的 ListFrm,直接传入存储库。

【讨论】:

我试图创建一个工厂,但我最终需要再次手动提供 ListFrm 依赖项。所以我认为这不是最好的解决方案。

以上是关于如何使用依赖注入多次创建对象的主要内容,如果未能解决你的问题,请参考以下文章

Spring依赖注入就是这么简单

依赖注入(Dependency Injection)框架是如何实现的?

SpringHelloSpring,IOC创建对象的方式,Spring配置,依赖注入

自定义容器,利用依赖注入创建对象

Spring详解------DI依赖注入

对动态创建的对象的依赖注入