2011-01-28 25 views
6

Tôi có mẫu bộ điều hợp (trình bao bọc) qua lớp cổng nối tiếp. Tôi có nên thực hiện mẫu IDisposable và gọi _wrappedSerialPort.Dispose() trong đó không? Có lớp của tôi, đúng không?Là SerialPort trong tài nguyên không được quản lý .NET? Lớp bọc của tôi có đúng không?

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: Có cần phải gọi này, hoặc là đủ để gọi chỉ _wrappedSerialPort.Dispose() ;?

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

Trả lời

5

Câu trả lời của Henk Holterman là chính xác: SerialPort là tài nguyên được quản lý, chính nó sở hữu tài nguyên không được quản lý và do đó triển khai IDisposable.

Vì trình bao bọc của bạn sở hữu một SerialPort, nó gián tiếp sở hữu tài nguyên không được quản lý của SerialPort và do đó phải triển khai IDisposable. Việc triển khai của bạn sai, trường hợp SerialPort được sở hữu chỉ nên được xử lý nếu disposing là đúng, vì đó là tài nguyên được quản lý.

Nó cần được thực hiện như sau:

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

Ngoài ra, như Henk Holterman chỉ ra, bạn chỉ cần một destructor nếu bạn trực tiếp nguồn lực không được quản lý riêng, mà không phải là trường hợp ở đây, và bạn có thể đơn giản hóa việc triển khai IDisposable bằng cách loại bỏ destructor.

+0

Đây là điều chỉnh đúng, tôi đã không xem xét Dispose() đủ gần. –

1
  • Vâng, nồi nối tiếp là một báo cáo không được quản lý. Hay bạn đã bao giờ thấy một nhà sưu tập rác cho HARDWARE VẬT LÝ? ;)

  • Điều này được thể hiện bởi lớp để truy cập triển khai IDisposable - điều đó có nghĩa là lớp của bạn lưu trữ một thuật ngữ dài hạn giới thiệu nhiều hơn để THỰC HIỆN IDISPOSABLE, TOO.

+0

Lớp bọc của tôi là chính xác? – Simon

+0

Tôi tự hỏi nếu tôi nên gọi gần, sau đó unregister sự kiện và sau đó vứt bỏ trong Dispose phương pháp. Nên đủ để gọi chỉ vứt bỏ? Làm thế nào về các sự kiện? – Simon

+0

Cổng nối tiếp là một tài nguyên không được quản lý, nhưng lớp SerialPort là một tài nguyên được quản lý. – Joe

0

Có, bạn đang thực hiện đúng phương pháp Dispose trong trường hợp này. Đảm bảo thêm IDisposable vào khai báo lớp học của bạn. Điều này làm cho nó có thể sử dụng rất tiện dụng using xây dựng, như thế này:

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

gọi Vứt bỏ trên cổng serial bọc nó đã có đủ, vì điều này sẽ đóng cổng. Theo tài liệu MS, Close sẽ gọi số Dispose nội bộ. Không có hại trong việc rõ ràng trong ý định của bạn bằng cách rõ ràng gọi Close, mặc dù.

Hủy đăng ký khỏi sự kiện, như bạn đang làm, là thực hành tốt.

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

6

Các SerialPort chính nó là chủ sở hữu của một nguồn lực không được quản lý và đó là lý do tại sao nó thực hiện các mô hình Disposable đầy đủ.

Trong lớp học, _wrappedSerialPort là một tài nguyên được quản lý. Định nghĩa của tôi: a tài nguyên được quản lý là gián tiếp tài nguyên không được quản lý.

Lớp học của bạn không không cần mẫu đầy đủ. Bạn có thể và nên bỏ qua các destructor (hoặc finalizer), ~SerialPortAdapter() và sau đó bạn có thể bỏ qua SupressFinalize. Bạn có thể dễ dàng rút ngắn mã nhiều hơn (vì void Dispose(bool) sẽ không bao giờ được gọi với số false).

Các vấn đề liên quan