2013-12-10 2 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 메서드의 로컬 참조 만 사용합니다.

refcurrentObject 파라미터있어서 ReleaseObject에 전달하는 것이며, 상기 변경 반원 NULL, 대신 object 데이터 형식 제네릭을 사용해야한다.

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

하고이 같은 변경이 메서드 호출 : : 그래서 방법이 될 것 그대로 당신은 ReleaseObject 방법의 몸을 남길 수 있습니다

ReleaseObject(ref m_excelWorkSheet); 

을,하지만 난 GC.Collect()를 호출하는 것은 아니라고 생각 필요한 경우, 그리고 정말로해야한다면, ReleaseObject을 모든 객체에 대해 호출 한 후, 결국 한 번만 DisposeExcelDocument에서 전화하십시오.

+0

감사합니다. 그런 다음 오류가 발생합니다. 'ref Microsoft.Office.Interop.Excel.Worksheet'에서 'ref object'로 변환 할 수 없습니다. – Idanis

+0

죄송합니다. 완전히 누락되었습니다. 다형성은'ref' 매개 변수로는 작동하지 않습니다. 여기에 제네릭이 필요합니다. – Ammar

+0

나는 대답을 바꿨다, 지금 그것이 효과가 있기를 바란다. 늦은 응답을 드려서 죄송합니다. – Ammar