【发布时间】:2016-01-11 08:45:08
【问题描述】:
我有一个使用 Unity for DI 的 N 层 WinForms 应用程序。 Main的启动如下:
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var container = new UnityContainer();
container.RegisterType<IProductRequestRepository, MDIS.DAL.Repositories.Specific.ProductRequestRepository>();
container.RegisterType<IProductRequestServices, ProductRequestServices>();
var form = container.Resolve<MdisMain>();
Application.Run(form);
}
IDisposable 在存储库 (ProductRequestRepository) 中实现。 ProductRequestServices 类的一个实例由主 WinForm 持有。因此,除非应用程序关闭,否则不会发布。 ProductRequestServices 类还有一个 ProductRequestRepository 实例。每次主窗口启动浏览表单时都会使用存储库,该表单使用存储库获取使用实体框架的条目列表。存储库有一个 DBContext 实例,它在实例化时创建。我在存储库实现 Dispose 方法中放置了断点,但它们从未被调用,可能是因为 ProductRequestServices 对象持有存储库的一个实例。
如果我在浏览窗口关闭时添加代码以在存储库实例上手动调用 Dispose,我会在重新打开浏览窗口时收到错误消息,说明对象为空,所以我猜 Unity 不会重新实例化对象同样,仅在组合根中的应用程序开始时。
在这种情况下,我是否应该在每次创建浏览窗口时重新实例化我的存储库类以确保 DBContext 是新的而不是以前的内容?这就是我打算做的事情,除非我可以让 Unity 做其他事情。打开主窗体后,我无法再次调用 Resolve 或任何 Unity 方法,因为我的 Unity 容器的范围仅限于我之前显示的启动主程序文件。我能做些什么来解决这种情况?提前致谢。
**** 更新于 2016 年 1 月 11 日晚上 9:40
目前,解决此问题的最简单方法是删除 Unity 容器,然后将表单调用(由 WinForm 主菜单选项启动)包装在 using 语句中,如下所示:
private void detailReportListToolStripMenuItem_Click_1(object sender, EventArgs e)
{
using (UnitOfWork aUnitOfWork = new UnitOfWork())
{
ProductRequestServices aProductRequestServices = new ProductRequestServices(aUnitOfWork);
ProductRequestList aProductRequestList = new ProductRequestList(aProductRequestServices);
aProductRequestList.ShowDialog();
aProductRequestList.Close();
}
}
我还从存储库中删除了 DBContext 内部实例,并将其放入 UnitOfWork 类中。上面的示例允许使用其内部 DBContext 实例化我的 UnitOfWork 类并将其传递到表单中,以便在存储库调用中使用它。当表单关闭时,UnitOfWork 被释放,这导致它的 Dispose 实现运行并释放表单使用的 DBContext。每次打开表单时,我都会得到一个 DBContext 的新实例。当我在应用程序启动时使用 Unity 容器时,它保留了 ProductRequestServices 类实例的单个实例,这导致了不释放 DBContext 的问题。手动尝试释放 DBContext 只会导致更多问题,因此这种方法现在可以使用。
【问题讨论】:
标签: c# winforms dependency-injection inversion-of-control unity-container