托管代理对本机对象的深度复制(在构造期间传递委托)

时间:2015-02-25 09:45:39

标签: c# delegates pinvoke

我有一个具有树重要功能的原生API,CreateObjectDestroyObjectCloneObject,并且CreateObject期望一个函数指针,我绑定到某些{托管代码中的{1}}:

NativeDelegate

然后,我在托管代码中为本地生活的对象创建了一个代理,如下所示:

[UnmanagedFunctionPointer]
public delegate double NativeDelegate(double);

internal static class NativeInterop
{
    [DllImport("native.dll", EntryPoint="CreateObject")]
    public static extern IntPtr CreateObject(NativeDelegate fctn);

    [DllImport("native.dll", EntryPoint="DestroyObject")]
    public static extern void DestroyObject(IntPtr pa);

    [DllImport("native.dll", EntryPoint="CloneObject")]
    public static extern IntPtr CloneObject(IntPtr pa);
}
NB:对于我到目前为止所做的测试,这一切都很好。 对我来说唯一的诀窍是保持构造函数的委托活着,因为它可能不再在托管代码中被引用,同时仍被其他本机API调用通过代理使用(未在示例代码中报告) )

现在我想知道如何克隆这个代理。目前我正在考虑:

public class NativeObject : IDisposable
{
    public NativeObject(NativeDelegate fctn)
    {
        pa = NativeInterop.CreateObject(fctn);
        keepAlive = fctn; // Because delegate may no longer be referenced anywhere else in managed code.
    }
    public Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    protected virtual void dispose(bool disposing)
    {
        if (pa == IntPtr.Zero) { return; }
        NativeInterop.DestroyObject(pa);
        pa = IntPtr.Zero;
    }
    ~NativeObject()
    {
        Dispose(false);
    }

    private NativeDelegate keepAlive;
    private IntPtr pa;
}

因为我已阅读herehere,委托是不可变的。

我有点自信这是可以的......但不知怎的,我也在蛋壳上行走......你能否证实我克隆代理是这样的,我不会陷入竞争状态我已经避风港了还没想到呢?是否可以制作代理的表面副本,即使是lambda,lambda引用本地范围变量?

例如:

public NativeObject Clone()
{
    if (pa == IntPtr.Zero) { throw new InvalidOperationException("Already disposed"); }

    var _pa = NativeInterop.CloneObject(pa); // Ask native API to make deep-copy on its side
    var _keepAlive = keepAlive; // Make shallow copy only for the delegate

    return new NativeObject(_pa, _keepAlive);
}
private NativeObject(IntPtr pa, NativeDelegate keepAlive)
{
    this.pa = pa;
    this.keepAlive = keepAlive; 
}

0 个答案:

没有答案