使用静态类中的非托管资源

时间:2012-09-14 08:24:55

标签: c# oop architecture

我有一个类,我认为使静态更有意义,因为它基本上是一个实用类。作为本课程的一部分,我正在使用Microsoft Access和Microsoft Excel。

显然,Office Interop对象是非托管资源,静态类不能有析构函数。我觉得只有Excel.Application对象的一个​​实例和我的各种方法可以使用的Access.Application对象的一个​​实例,注意关闭我的数据库和工作簿,以及妥善处理错误。

当我关闭程序时出现问题,如果我没有运行System.Runtime.InteropServices.Marshal.ReleaseComObject("myOfficeApplicationInstance");,Office实例就会在我的任务管理器中出现。如果我在应用程序运行时释放该对象,则无法再次使用它。

我不确定这一切是否有意义所以有些代码如下:

using System;
using Excel = Microsoft.Office.Interop.Excel.Application;
using Access = Microsoft.Office.Interop.Access.Application;

namespace QWERTY
{
    internal static class CreateReport
    {
        private static readonly Excel _excel;
        private static readonly Access _access;

        static CreateReport()
        {
            _excel = new Excel();
            _access = new Access();
        }

        internal static void Performance(DateTime reportDate)
        {
            _excel.Workbooks.Open(@"C:\whatever.xlsx");

            //Do stuff with Excel

            _excel.Workbooks.Close();

            _access.OpenCurrentDatabase(@"C:\whatever.accdb");

            //Do stuff with Access

            _access.CloseCurrentDatabase();
        }
    }
}

几个问题

  1. 我是对的,这应该是一个静态类吗?
  2. 当我使用静态类时,如何处理非托管资源?

4 个答案:

答案 0 :(得分:2)

没有静态终结器(参见here)。如果要使类保持静态,还要添加一个方法来清理在应用程序结束时调用的方法。

替代方案(我更喜欢)是拥有singleton instance,并在应用程序结束时清理此实例。

如果需要,您还可以使用静态属性来访问实例。静态属性的替代方法是使用某种形式的DI,您可以将其配置为创建单个实例。大多数DI提供单例范围。

答案 1 :(得分:2)

如果您希望继承静态方式实现继承the CriticalFinalizerObject Class的类。将静态类清理放在它的终结器中,然后将该类的一个实例添加为静态类的字段。然后,如果应用程序退出或您的应用程序域卸载该实例终结器将运行清理静态类。

答案 2 :(得分:1)

处理非托管资源的最佳方法是将它们包装在实现IDisposable的类中。然后,您应该在using块中使用该类以确保正确清理。由于所有包含IDisposable成员的类本身都应该是IDisposable,因此将它们设置为静态类成员并不是一个好主意。

当你的应用程序退出时,你总是可以释放它们,你们确实有这个事件。

您确定无法在应用程序中打开Excel两次吗?

答案 3 :(得分:0)

很抱歉,Office Interop对象被视为托管资源,因为Excel和Access不会实现Idisposable接口。

您是否尝试使用 Excel.Quit 声明正确关闭应用程序?我在你发布的代码中没有看到它。