using System;
using System.Runtime.InteropServices;
namespace Developpez.Dotnet
{
///
/// Représente un pointeur non managé qui implémente IDisposable pour libérer la ressource.
///
public class DisposablePointer : IDisposable
{
///
/// Initialise une nouvelle instance de DisposablePointer, avec la valeur spécifiée et
/// l'action spécifiée pour libérer le pointeur.
///
/// Valeur initiale du pointeur
/// Action à exécuter pour libérer le pointeur
public DisposablePointer(IntPtr value, Action disposeAction)
{
this._value = value;
this._disposeAction = disposeAction;
}
private bool _disposed = false;
private readonly IntPtr _value;
private Action _disposeAction;
///
/// Renvoie la valeur du pointeur
///
/// L'objet a été disposé et le pointeur libéré
public IntPtr Value
{
get
{
if (_disposed)
throw new ObjectDisposedException("DisposablePointer");
return _value;
}
}
///
/// Libère la ressource représentée par le pointeur, en appelant l'action spécifiée
/// en paramètre du constructeur
///
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
///
/// Destructeur
///
~DisposablePointer()
{
this.Dispose(false);
}
///
/// Libère la ressource représentée par le pointeur, en appelant l'action spécifiée
/// en paramètre du constructeur
///
/// Inutilisé
protected virtual void Dispose(bool disposing)
{
if (_disposeAction != null && _value != IntPtr.Zero)
_disposeAction(_value);
_disposed = true;
}
#if !SILVERLIGHT // Marshal.AllocHGlobal n'est pas supporté en SL
///
/// Alloue la quantité spécifiée de mémoire non managée, et renvoie le pointeur obtenu
/// sous forme d'un DisposablePointer.
///
/// Quantité de mémoire à allouer
/// Un DisposablePointer représentant la zone mémoire allouée
public static DisposablePointer AllocHGlobal(int size)
{
return new DisposablePointer(Marshal.AllocHGlobal(size), Marshal.FreeHGlobal);
}
#endif
///
/// Méthode d'extension qui crée un wrapper IDisposable pour un pointeur
///
/// Le pointeur à wrapper
/// L'action à effectuer pour libérer la ressource
/// Un objet IDisposable qui wrappe le pointeur
public static DisposablePointer AsDisposable(IntPtr value, Action disposeAction)
{
return new DisposablePointer(value, disposeAction);
}
}
}