2011-01-28 2 views
6

직렬 포트 클래스에 어댑터 패턴 (래퍼)이 있습니다. 내가 IDisposable 패턴을 구현하고 그것에 _wrappedSerialPort.Dispose()를 호출해야합니까? 제 수업이 있어요, 맞습니까?.NET에서 SerialPort가 관리되지 않는 리소스입니까? 포장 된 수업이 맞습니까?

public class SerialPortAdapter : ISerialPortAdapter 
{ 
    private bool _disposed; 

    public event SerialDataReceivedEventHandler DataReceived; 

    private readonly SerialPort _wrappedSerialPort; 

    public SerialPort WrappedSerialPort 
    { 
     get { return _wrappedSerialPort; } 
    } 

    public string PortName 
    { 
     get { return _wrappedSerialPort.PortName; } 
     set { _wrappedSerialPort.PortName = value; } 
    } 

    public BaudRate BaudRate 
    { 
     get { return (BaudRate)Enum.ToObject(typeof(BaudRate), _wrappedSerialPort.BaudRate); } 
     set { _wrappedSerialPort.BaudRate = (int)value; } 
    } 

    public bool IsOpen 
    { 
     get { return WrappedSerialPort.IsOpen; } 
    } 

    public SerialPortAdapter(SerialPort serialPort) 
    { 
     _wrappedSerialPort = serialPort; 
     _wrappedSerialPort.DataReceived += SerialPortDataReceived; 
    } 

    public void OpenPort() 
    { 
     if (!_disposed) 
     { 
      if (!WrappedSerialPort.IsOpen) 
      { 

       WrappedSerialPort.Open(); 

      } 
     } 
    } 


    public void ClosePort() 
    { 
     if (!_disposed) 
     { 
      if (WrappedSerialPort.IsOpen) 
      { 

       WrappedSerialPort.Close(); 

      } 
     } 
    } 


    public void WriteLine(string request) 
    { 
    ... 
    } 


    public void Write(byte[] request) 
    { 
     .... 
    } 


    public byte[] Read() 
    { 
     .... 
    } 


    public string ReadLine() 
    { 
     ... 
    } 


    private void SerialPortDataReceived(object sender, SerialDataReceivedEventArgs e) 
    { 
     if (DataReceived != null) 
     { 
      DataReceived(this, e); 
     } 
    } 

    #region IDisposable Members 

    public virtual void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (!_disposed) 
     { 
      if (disposing) 
      { 
       // Dispose managed resources. 

      } 
      // Dispose unmanaged resources. 

      ClosePort(); 
      WrappedSerialPort.DataReceived -= SerialPortDataReceived; 
      _wrappedSerialPort.Dispose(); 

      _disposed = true; 

     } 
    } 

    ~SerialPortAdapter() 
    { 

     Dispose(false); 
    } 

    #endregion 
} 

편집 : 이것을 호출해야합니까, 아니면 _wrappedSerialPort.Dispose(); 만 호출하면됩니까?

 ClosePort(); 
     WrappedSerialPort.DataReceived -= SerialPortDataReceived; 
     _wrappedSerialPort.Dispose(); 

답변

5

흠호 홀터 먼 (Henk Holterman)의 대답은 정확합니다. SerialPort는 자체 관리 리소스를 소유하므로 관리되는 리소스이므로 IDisposable을 구현합니다.

래퍼가 SerialPort를 소유하고 있으므로 간접적으로은 SerialPort의 관리되지 않는 리소스를 소유하므로 IDisposable을 구현해야합니다. 구현이 잘못되어 소유 한 SerialPort 인스턴스는 관리 자원이므로 disposing이 참인 경우에만 처리해야합니다.다음과 같이

그것은 구현해야합니다

private void Dispose(bool disposing) 
    { 
     if (!_disposed) 
     { 
      if (disposing) 
      { 
       // Dispose managed resources. 
       ClosePort(); 
       WrappedSerialPort.DataReceived -= SerialPortDataReceived; 
       _wrappedSerialPort.Dispose(); 
      } 
      _disposed = true; 
     } 
    } 

또한, 헹크 Holterman가 지적한대로, 당신은 단지 소멸자를 필요로 직접 자신의 관리되지 않는 경우 여기 아닌 자원, 그리고 당신이 당신이 할 수있는 경우 소멸자 제거함으로써 IDisposable 구현을 단순화하십시오.

+0

이것은 올바른 교정입니다. Dispose()를 충분히 보지 않았습니다. –

1
  • 예, 시리얼 포트는 관리되지 않는 보고서입니다. 아니면 실제 하드웨어의 가비지 수집기를 보았습니까? ;)

  • 이것은 IDisposable을 구현하는 액세스 클래스에 의해 표시됩니다. 이는 귀하의 클래스가 오랜 기간을 호스팅하고 있음을 의미합니다. 너무 많이 구현 가능성이 있습니다.

+0

래핑 된 클래스가 맞습니까? – Simon

+0

Iam이 close를 호출해야한다면 이벤트 등록을 취소 한 다음 Dispose 메서드로 처리해야할까요? 처분 만하는 데 충분해야합니까? 이벤트는 어떻습니까? – Simon

+0

직렬 포트는 관리되지 않는 리소스이지만 SerialPort 클래스는 관리되는 리소스입니다. – Joe

0

예,이 경우에는 Dispose 메서드를 구현하는 것이 옳습니다. 클래스 선언에 IDisposable을 추가해야합니다. 이 포트를 종료하기 때문에, 충분히로 랩 시리얼 포트에 폐기 호출

using (var port = new SerialPortAdapter(serialPort)) { 
    port.OpenPort(); 
    // use port 
} 

마땅 : 이것에이 같은 매우 편리 using 구조를 사용 할 수 있습니다. MS 설명서에 따르면 CloseDispose을 내부적으로 호출합니다. 하지만 명시 적으로 Close을 호출하여 의도적으로 명확히하는 데 아무런 해가 없습니다.

이벤트에서 등록을 취소하는 것은 좋은 일입니다.

http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.close.aspx

6

는하여 SerialPort 자체는 관리되지 않는 리소스의 소유자와는 전체 일회용 패턴을 구현하는 이유입니다.

클래스에서 _wrappedSerialPort 리소스입니다. 내 정의 : 관리되는 리소스은 간접적 인 비 관리 리소스입니다.

클래스는 이 아니며은 전체 패턴이 필요합니다. 당신은 소멸자 (또는 파이널 라이저) 인 ~SerialPortAdapter()을 생략 할 수 있고 그 다음에는 SupressFinalize를 건너 뛸 수 있습니다.

나머지는 남겨 두는 것이 가장 좋지만 코드를 더 많이 단축하는 것이 쉽습니다 (void Dispose(bool)false으로 호출되지 않으므로).

관련 문제