解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
|
# ¿ÉÏú»Ù DisposeBase
## ¸ÅÊö
`DisposeBase` ÊÇ NewLife.Core ÖÐʵÏÖ `IDisposable` ģʽµÄ³éÏó»ùÀ࣬Ìṩ±ê×¼µÄ×ÊÔ´ÊÍ·Åģʽ£¬ÓÐЧ·ÀÖ¹ÄÚ´æºÍ×ÊԴй©¡£ËüÈ·±£ÊÍ·ÅÂß¼Ö»Ö´ÐÐÒ»´Î£¬²¢Ö§³ÖÏú»Ùʼþ֪ͨ¡£
**ÃüÃû¿Õ¼ä**£º`NewLife`
**ÎĵµµØÖ·**£ºhttps://newlifex.com/core/disposebase
## ºËÐÄÌØÐÔ
- **±ê×¼ Dispose ģʽ**£ºÕýȷʵÏÖ `IDisposable` ½Ó¿Ú
- **µ¥´ÎÊͷű£Ö¤**£ºÍ¨¹ýÔ×Ó²Ù×÷È·±£ÊÍ·ÅÂß¼Ö»Ö´ÐÐÒ»´Î
- **ÖÕ½áÆ÷Ö§³Ö**£ºÔÚÍü¼Çµ÷Óà `Dispose` ʱÌṩ¶µµ×ÊÍ·Å
- **Ïú»Ùʼþ**£ºÖ§³ÖÔÚ¶ÔÏóÏú»Ùʱ´¥·¢Ê¼þ֪ͨ
- **¸¨Öú·½·¨**£ºÌṩ `ThrowIfDisposed` ºÍ `TryDispose` µÈ¸¨Öú·½·¨
## ¿ìËÙ¿ªÊ¼
```csharp
using NewLife;
// ¼Ì³Ð DisposeBase ʵÏÖ×ÊÔ´¹ÜÀí
public class MyResource : DisposeBase
{
private Stream _stream;
public MyResource(String path)
{
_stream = File.OpenRead(path);
}
protected override void Dispose(Boolean disposing)
{
base.Dispose(disposing);
if (disposing)
{
// ÊÍ·ÅÍйÜ×ÊÔ´
_stream?.Dispose();
_stream = null;
}
}
}
// ʹÓà using Óï¾ä×Ô¶¯ÊÍ·Å
using var resource = new MyResource("data.txt");
```
## API ²Î¿¼
### IDisposable2 ½Ó¿Ú
```csharp
public interface IDisposable2 : IDisposable
{
Boolean Disposed { get; }
event EventHandler OnDisposed;
}
```
À©Õ¹µÄ¿ÉÏú»Ù½Ó¿Ú£¬Ôö¼ÓÁË `Disposed` ״̬ÊôÐÔºÍÏú»Ùʼþ¡£
### DisposeBase Àà
#### ÊôÐÔ
##### Disposed
```csharp
public Boolean Disposed { get; }
```
±íʾ¶ÔÏóÊÇ·ñÒѱ»ÊÍ·Å¡£
**ʾÀý**£º
```csharp
var resource = new MyResource();
Console.WriteLine(resource.Disposed); // False
resource.Dispose();
Console.WriteLine(resource.Disposed); // True
```
#### ·½·¨
##### Dispose
```csharp
public void Dispose()
```
ÊÍ·Å×ÊÔ´¡£µ÷Óúó»á´¥·¢ `OnDisposed` ʼþ£¬²¢Í¨Öª GC ²»ÔÙµ÷ÓÃÖÕ½áÆ÷¡£
##### Dispose(Boolean)
```csharp
protected virtual void Dispose(Boolean disposing)
```
ʵ¼ÊµÄ×ÊÔ´ÊÍ·Å·½·¨£¬×ÓÀàÖØÔØ´Ë·½·¨ÊµÏÖ¾ßÌåµÄÊÍ·ÅÂß¼¡£
**²ÎÊý˵Ã÷**£º
- `disposing`£º`true` ±íʾ´Ó `Dispose()` ·½·¨µ÷Óã¬Ó¦ÊÍ·ÅËùÓÐ×ÊÔ´£»`false` ±íʾ´ÓÖÕ½áÆ÷µ÷Óã¬Ö»Ó¦ÊÍ·Å·ÇÍйÜ×ÊÔ´
**ÖØÔØÊ¾Àý**£º
```csharp
protected override void Dispose(Boolean disposing)
{
// 1. Ê×Ïȵ÷ÓûùÀà·½·¨
base.Dispose(disposing);
// 2. ÊÍ·ÅÍйÜ×ÊÔ´£¨½öµ±´Ó Dispose() µ÷ÓÃʱ£©
if (disposing)
{
_managedResource?.Dispose();
_managedResource = null;
}
// 3. ÊÍ·Å·ÇÍйÜ×ÊÔ´£¨Á½ÖÖ·¾¶¶¼Ö´ÐУ©
if (_handle != IntPtr.Zero)
{
CloseHandle(_handle);
_handle = IntPtr.Zero;
}
}
```
##### ThrowIfDisposed
```csharp
protected void ThrowIfDisposed()
```
ÔÚ¹«¿ª·½·¨Öе÷Óã¬Èô¶ÔÏóÒÑÊÍ·ÅÔòÅ׳ö `ObjectDisposedException`¡£
**ʾÀý**£º
```csharp
public class MyResource : DisposeBase
{
public void DoWork()
{
ThrowIfDisposed(); // ÒÑÊÍ·ÅʱÅ׳öÒì³£
// Ö´ÐÐʵ¼Ê¹¤×÷...
}
}
```
#### ʼþ
##### OnDisposed
```csharp
public event EventHandler? OnDisposed
```
¶ÔÏó±»Ïú»Ùʱ´¥·¢µÄʼþ¡£
**×¢Òâ**£ºÊ¼þ¿ÉÄÜÔÚÖÕ½áÆ÷Ïß³ÌÖд¥·¢£¬¶©ÔÄ·½Ó¦±ÜÃâÒÀÀµÌض¨Ïß³ÌÉÏÏÂÎÄ¡£
**ʾÀý**£º
```csharp
var resource = new MyResource();
resource.OnDisposed += (sender, e) =>
{
Console.WriteLine("×ÊÔ´ÒÑÊÍ·Å");
};
resource.Dispose(); // Êä³ö£º×ÊÔ´ÒÑÊÍ·Å
```
### DisposeHelper ¸¨ÖúÀà
#### TryDispose
```csharp
public static Object? TryDispose(this Object? obj)
```
³¢ÊÔÏú»Ù¶ÔÏó£¬Èç¹û¶ÔÏóʵÏÖÁË `IDisposable` Ôòµ÷ÓÃÆä `Dispose` ·½·¨¡£Ö§³Ö¼¯ºÏÀàÐÍ£¬»á±éÀúÏú»ÙËùÓÐÔªËØ¡£
**ʾÀý**£º
```csharp
// Ïú»Ùµ¥¸ö¶ÔÏó
var stream = File.OpenRead("test.txt");
stream.TryDispose();
// Ïú»Ù¼¯ºÏÖеÄËùÓжÔÏó
var streams = new List<Stream>
{
File.OpenRead("a.txt"),
File.OpenRead("b.txt"),
File.OpenRead("c.txt")
};
streams.TryDispose(); // Ïú»ÙËùÓÐÁ÷
```
## ʹÓó¡¾°
### 1. ¹ÜÀíÎļþ¾ä±ú
```csharp
public class FileProcessor : DisposeBase
{
private FileStream? _fileStream;
private StreamReader? _reader;
public FileProcessor(String path)
{
_fileStream = File.OpenRead(path);
_reader = new StreamReader(_fileStream);
}
public String ReadLine()
{
ThrowIfDisposed();
return _reader?.ReadLine() ?? String.Empty;
}
protected override void Dispose(Boolean disposing)
{
base.Dispose(disposing);
if (disposing)
{
_reader?.Dispose();
_reader = null;
_fileStream?.Dispose();
_fileStream = null;
}
}
}
```
### 2. ¹ÜÀíÍøÂçÁ¬½Ó
```csharp
public class TcpConnection : DisposeBase
{
private Socket? _socket;
private NetworkStream? _stream;
public TcpConnection(String host, Int32 port)
{
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
_socket.Connect(host, port);
_stream = new NetworkStream(_socket, ownsSocket: false);
}
public void Send(Byte[] data)
{
ThrowIfDisposed();
_stream?.Write(data, 0, data.Length);
}
protected override void Dispose(Boolean disposing)
{
base.Dispose(disposing);
if (disposing)
{
_stream?.Dispose();
_stream = null;
_socket?.Dispose();
_socket = null;
}
}
}
```
### 3. ×ÊÔ´³Ø¹ÜÀí
```csharp
public class ResourcePool<T> : DisposeBase where T : IDisposable
{
private readonly ConcurrentBag<T> _pool = new();
private readonly Func<T> _factory;
public ResourcePool(Func<T> factory)
{
_factory = factory;
}
public T Rent()
{
ThrowIfDisposed();
return _pool.TryTake(out var item) ? item : _factory();
}
public void Return(T item)
{
if (Disposed)
{
item.Dispose();
return;
}
_pool.Add(item);
}
protected override void Dispose(Boolean disposing)
{
base.Dispose(disposing);
if (disposing)
{
while (_pool.TryTake(out var item))
{
item.Dispose();
}
}
}
}
```
### 4. ¼àÌýÏú»Ùʼþ
```csharp
public class ResourceMonitor
{
public void Monitor(IDisposable2 resource)
{
resource.OnDisposed += (sender, e) =>
{
var name = sender?.GetType().Name;
Console.WriteLine($"[{DateTime.Now:HH:mm:ss}] {name} ÒÑÊÍ·Å");
};
}
}
// ʹÓÃ
var monitor = new ResourceMonitor();
var resource = new MyResource();
monitor.Monitor(resource);
resource.Dispose(); // Êä³ö£º[12:30:45] MyResource ÒÑÊÍ·Å
```
## ×î¼Ñʵ¼ù
### 1. ×ÜÊǵ÷ÓûùÀà·½·¨
```csharp
protected override void Dispose(Boolean disposing)
{
// ? Ê×Ïȵ÷ÓûùÀà·½·¨
base.Dispose(disposing);
// È»ºóÊÍ·Å×Ô¼ºµÄ×ÊÔ´
if (disposing) { /* ... */ }
}
```
### 2. ʹÓà using Óï¾ä
```csharp
// ? ÍÆ¼ö£ºÊ¹Óà using Óï¾äÈ·±£ÊÍ·Å
using var resource = new MyResource();
// ? ²»ÍƼö£ºÊÖ¶¯µ÷Óà Dispose£¬ÈÝÒ×ÒÅÍü
var resource = new MyResource();
try
{
// ʹÓÃ×ÊÔ´
}
finally
{
resource.Dispose();
}
```
### 3. ÔÚ¹«¿ª·½·¨Öмì²é״̬
```csharp
public class MyResource : DisposeBase
{
public void DoWork()
{
// ? ÔÚ·½·¨¿ªÊ¼Ê±¼ì²éÊÇ·ñÒÑÊÍ·Å
ThrowIfDisposed();
// Ö´ÐÐʵ¼Ê¹¤×÷
}
}
```
### 4. ÕýÈ·´¦ÀíÍйܺͷÇÍйÜ×ÊÔ´
```csharp
protected override void Dispose(Boolean disposing)
{
base.Dispose(disposing);
// ÍйÜ×ÊÔ´£º½öÔÚ disposing=true ʱÊÍ·Å
if (disposing)
{
_managedObject?.Dispose();
}
// ·ÇÍйÜ×ÊÔ´£ºÁ½ÖÖÇé¿ö¶¼ÒªÊÍ·Å
if (_nativeHandle != IntPtr.Zero)
{
NativeMethods.CloseHandle(_nativeHandle);
_nativeHandle = IntPtr.Zero;
}
}
```
### 5. ±ÜÃâÔÚÖÕ½áÆ÷ÖÐÅ׳öÒì³£
```csharp
// DisposeBase ÒѾ´¦ÀíÁËÖÕ½áÆ÷ÖеÄÒì³£
// ×ÓÀàµÄ Dispose(Boolean) ·½·¨Ò²Ó¦¸Ã²¶»ñ¿ÉÄܵÄÒì³£
protected override void Dispose(Boolean disposing)
{
base.Dispose(disposing);
try
{
// ÊÍ·Å×ÊÔ´
}
catch (Exception ex)
{
// ¼Ç¼µ«²»Å׳ö
XTrace.WriteException(ex);
}
}
```
## Dispose ģʽÏê½â
```
µ÷ÓÃ Dispose()
©¦
¨‹
Dispose(true)
©¦
©À©¤©¤? ÊÍ·ÅÍйÜ×ÊÔ´
©¦
©À©¤©¤? ÊÍ·Å·ÇÍйÜ×ÊÔ´
©¦
©À©¤©¤? ´¥·¢ OnDisposed ʼþ
©¦
©¸©¤©¤? GC.SuppressFinalize(this)
©¦
©¸©¤©¤? ÖÕ½áÆ÷²»ÔÙ±»µ÷ÓÃ
ÖÕ½áÆ÷ ~DisposeBase() (Èç¹ûÍü¼Çµ÷Óà Dispose)
©¦
¨‹
Dispose(false)
©¦
©À©¤©¤? ÊÍ·Å·ÇÍйÜ×ÊÔ´
©¦
©¸©¤©¤? ´¥·¢ OnDisposed ʼþ
```
## Ïà¹ØÁ´½Ó
- [¶ÔÏó³Ø ObjectPool](/NewLife/X/Blob/master/Doc/object_pool-¶ÔÏó³ØObjectPool.md)
- [¶ÔÏóÈÝÆ÷ ObjectContainer](/NewLife/X/Blob/master/Doc/object_container-¶ÔÏóÈÝÆ÷ObjectContainer.md)
|