2013-12-10 129 views
0

我有一个实现Excel相关函数(类库)的静态类。处理静态对象c#

这个DLL被添加为其他应用程序的参考,我试图使用这些功能。

我知道静态对象在主程序终止时被放弃。我能以某种方式处置它吗?

在我的代码中,如果我调用CreateExcelDocument(excelFile),并且Excel的实例在后台运行(我可以在Windows的进程管理器中看到它)。但是,当我拨打DisposeExcelDocument();时,该实例依然存在。我该如何处置它?

我的目标是逐个打开多个Excel文件,从当前打开的文件创建图形,然后关闭并移至下一个文件。它甚至有可能吗?

下面是代码:

所有与我有关使这个非静态类的意见赞成的
public static class ExcelUtils 
{ 
    #region Private Members 

    private static Application m_excelApp; 
    private static Workbook m_excelWorkBook; 
    private static Worksheet m_excelWorkSheet; 

    #endregion Private Members 

    #region Properties 

    public static Worksheet ExcelWorkSheet 
    { 
     get { return m_excelWorkSheet; } 
     set { m_excelWorkSheet = value; } 
    } 

    #endregion Properties 

    #region Public Functions 

    public static void CreateExcelDocument(string excelFile) 
    { 
     try 
     { 
      m_excelApp = new Application(); 
      m_excelApp.DisplayAlerts = false; 
      m_excelWorkBook = m_excelApp.Workbooks.Add(Type.Missing); 
      m_excelWorkSheet = (Worksheet)m_excelApp.ActiveSheet; 
      m_excelApp.DefaultSheetDirection = (int)Constants.xlLTR; 
      m_excelWorkSheet.DisplayRightToLeft = false; 

      if (excelFile.CompareTo("") != 0) 
      { 
       m_excelWorkBook = m_excelApp.Workbooks.Open(excelFile); 
       m_excelWorkSheet = (Worksheet)m_excelApp.Worksheets.get_Item(1); 
       m_excelWorkSheet.Columns.ClearFormats(); 
       m_excelWorkSheet.Rows.ClearFormats(); 
      } 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
      return; 
     } 
    } 
    public static void DisposeExcelDocument() 
    { 
     try 
     { 
      m_excelApp.Quit(); 
      ReleaseObject(m_excelWorkSheet); 
      ReleaseObject(m_excelWorkBook); 
      ReleaseObject(m_excelApp); 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine(ex.Message); 
      return; 
     } 
    } 

    public static void ReleaseObject(object currentObject) 
    { 
     try 
     { 
      System.Runtime.InteropServices.Marshal.ReleaseComObject(currentObject); 
      currentObject = null; 
     } 
     catch (Exception ex) 
     { 
      currentObject = null; 
      Console.WriteLine(ex.ToString()); 
      return; 
     } 
     finally 
     { 
      GC.Collect(); 
     } 

    } 

    public static uint GetNumberOfRowsOrCols(string excelFile, bool getRows) 
    { 
     CreateExcelDocument(excelFile); 

     uint rowColNum = 0; 

     if (getRows) 
      rowColNum = (uint)m_excelWorkSheet.UsedRange.Rows.Count; 
     else 
      rowColNum = (uint)m_excelWorkSheet.UsedRange.Columns.Count; 

     DisposeExcelDocument(); 

     return rowColNum; 
    } 

    #endregion Public Functions 
} 
+2

你有没有考虑*不是*将这些作为静态变量开始?是的,如果你真的想要,你可以处理它们 - 但是将这些变量作为实例变量会更清晰,并且可以让调用者根据需要创建单个实例或多个实例。毕竟,它本质上不是静态的。 –

+0

是的,我做过,但后来我不能从外部调用公共职能,他们希望是静态的。 – Idanis

+0

好的,您需要更改其他代码 - 但这会重构它以改进它。 –

回答

1

第一。

但是就您的问题而言,垃圾收集器不会收集对象,因为您没有将类设置为null,而只是ReleaseObject方法中的本地引用。

为NULL类成员与至少变化,将通过currentObject参数ReleaseObject方法ref,并且必须使用代替object数据类型泛型。因此,该方法将成为:

public static void ReleaseObject<T>(ref T currentObject) where T : class 

,并调用这个方法,你会改变这样的:

ReleaseObject(ref m_excelWorkSheet); 

你可以离开ReleaseObject方法体,因为它是,但我想呼吁GC.Collect()不如果您真的需要,那么在您为所有对象调用ReleaseObject之后,最后只需从DisposeExcelDocument调用一次。

+0

感谢Ammar。然后我得到的错误:'不能从'微软.Office.Interop.Excel.Worksheet'转换为'ref object'' – Idanis

+0

对不起,我完全错过了。多态性不能与'ref'参数一起工作。我们必须在这里需要泛型。 – Ammar

+0

我改变了答案,希望现在可以运作。抱歉迟了回应。 – Ammar