使用泛型管理本机句柄

时间:2010-09-27 20:14:54

标签: c# native handle

我有一个C#.NET 2.0 CF项目,我正在使用许多本机方法。其中一些方法围绕某种HANDLE对象。我想使用这样的泛型来抽象出句柄管理生命周期:

public abstract class IHandleTraits
{
    public abstract IntPtr Create();
    public abstract void Release(IntPtr handle);
}

public sealed class SafeHandle<T> : IDisposable where T : IHandleTraits
{
    private bool disposed;
    private IntPtr handle_ = NativeMethods.INVALID_HANDLE_VALUE;
    public SafeHandle()
    {
        // error CS0119: 'T' is a 'type parameter', which is not valid in the given context
        handle_ = T.Create();
        if (NativeMethods.INVALID_HANDLE_VALUE == handle_)
        {
            // throw win32 exceptions
        }
    }

    ~SafeHandle()
    {
        this.Dispose(false);
    }

    public IntPtr Handle
    {
        get { return handle_; }
    }

    public void Dispose(bool disposing)
    {
        if (this.disposed)
        {
            // error CS0119: 'T' is a 'type parameter', which is not valid in the given context
            T.Release(handle_);
            handle_ = NativeMethods.INVALID_HANDLE_VALUE;
        }
        this.disposed = true;
    }

    public void Dispose()
    {
        this.Dispose(true);
        GC.SuppressFinalize(this);
    }
}

现在,我可以为每个句柄类型定义一个traits结构,如下所示:

internal sealed class MyHandleTraits : IHandleTraits
{
    // error CS0112: A static member cannot be marked as override, virtual, or abstract
    public static override IntPtr Create()
    {
        return NativeMethods.CreateHandle();
    }

    // error CS0112: A static member cannot be marked as override, virtual, or abstract
    public static override void Release(IntPtr handle)
    {
        NativeMethods.ReleaseHandle(handle);
    }
}

在这样的应用程序中使用它:

using (SafeHandle<MyHandleTraits> MyHandle = new SafeHandle<MyHandleTraits>)
{
    // execute native methods with this handle
} 

显然,这有几个问题:

  1. 如何为abstract函数定义static接口?
  2. 当我尝试使用泛型时,我收到一个错误,指出它是“类型参数”,“在给定的上下文中无效”。
  3. 我可以做些什么来解决或解决这些问题?

    谢谢, PaulH

1 个答案:

答案 0 :(得分:1)

是的,无法工作。您需要实现IHandleTraits的类的实际实例。接口需要一个实现v表的类。只要你想密封这个类,你需要一个工厂或创建一个T.的实例。

实际上,对象层次结构是错误的。 SafeHandle应该是一个抽象基类,具有具体的派生类,每个类都知道如何处理特定的句柄类型。这也是SafeHandle的桌面版本的实现方式。

您可以通过赋予T new()约束来拯救您的方法,以便您可以创建它的实例。拖动额外的引用并不是那么好:

public sealed class SafeHandle<T> : IDisposable where T : IHandleTraits, new() {
    private bool disposed;
    private IntPtr handle_ = IntPtr.Zero;
    private T handleType;
    public SafeHandle() {
        handleType = new T();                        
        handle_ = handleType.Create();
    }
    // etc...
}