2011-01-28 35 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を実装するためのアクセスクラスで示されています。これは、あなたのクラスがIDLEPOSABLE、TOOに実装されています。

+0

ラップされたクラスは正しいですか? – Simon

+0

私は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で決して呼び出されないため、コードをもっと短くするのは簡単でしょう。

関連する問題