2013-12-10 209 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