Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is SerialPort in .NET unmanaged resource? Is my wrapped class correct?

I have adapter pattern (wrapper) over serial port class. Should I implement IDisposable pattern and call _wrappedSerialPort.Dispose() in it? There is my class, is it correct?

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
}

Edit: Is it necessary to call this, or is enough to call only _wrappedSerialPort.Dispose();?

        ClosePort();
        WrappedSerialPort.DataReceived -= SerialPortDataReceived;
        _wrappedSerialPort.Dispose();
like image 706
Simon Avatar asked Jan 28 '11 09:01

Simon


1 Answers

Henk Holterman's answer is correct: SerialPort is a managed resource, which itself owns an unmanaged resource and hence implements IDisposable.

Since your wrapper owns a SerialPort, it indirectly owns SerialPort's unmanaged resource and hence must implement IDisposable. Your implementation is wrong, the owned SerialPort instance should only be disposed if disposing is true, since it is a managed resource.

It should be implemented as follows:

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

Also, as Henk Holterman points out, you only need a destructor if you directly own unmanaged resources, which is not the case here, and you can simplify the IDisposable implementation by getting rid of the destructor.

like image 161
Joe Avatar answered Sep 23 '22 04:09

Joe