struct and destructor
I created the type IntPtr<T>
to act like a generic pointer that c/c++ have:
public struct IntPtr<T> : IDisposable where T : struct
{
private static Dictionary<IntPtr, GCHandle> handles = new Dictionary<IntPtr, GCHandle>();
private IntPtr ptr;
public IntPtr(ref T value)
{
GCHandle gc = GCHandle.Alloc(value, GCHandleType.Pinned);
ptr = gc.AddrOfPinnedObject();
handles.Add(ptr, gc);
}
public IntPtr(ref T[] value)
{
GCHandle gc = GCHandle.Alloc(value, GCHandleType.Pinned);
ptr = gc.AddrOfPinnedObject();
handles.Add(ptr, gc);
}
public IntPtr(IntPtr value)
{ ptr = value; }
public IntPtr(IntPtr<T> value)
{ ptr = value.ptr; }
public void Dispose()
{
if (handles.ContainsKey(ptr))
{
GCHandle gc = handles[ptr];
gc.Free();
handles.Remove(ptr);
ptr = IntPtr.Zero;
}
}
public T? this[int index]
{
get
{
if (ptr == IntPtr.Zero) return null;
if (index < 0) throw new IndexOutOfRangeException();
if (handles.ContainsKey(ptr))
{
GCHandle gc = handles[ptr];
if (gc.Target is Array) return ((T[])gc.Target)[index];
return (T)gc.Target;
}
return null;
}
set
{
if (index < 0) throw new IndexOutOfRangeException();
// not yet implemented
}
}
private T[] getArray()
{
if (handles.ContainsKey(ptr)) return (T[])handles[ptr].Target;
return null;
}
public int Count
{
get
{
if(handles.ContainsKey(ptr))
{
GCHandle gc = handles[ptr];
if (gc.Target is Array) return ((T[])gc.Target).Length;
return 1;
}
return 0;
}
}
public static implicit operator IntPtr(IntPtr<T> value) { return value.ptr; }
public static implicit operator T(IntPtr<T> value) { return (T)value[0]; }
public static implicit operator T[](IntPtr<T> value) { return value.getArray(); ; }
public static implicit operator T?(IntPtr<T> value) { return value[0]; }
}
It's not complete yet but for now it works, the problem is i keep track of GCHandle
by storing them in handles
now i need to free the GCHandle
once it no more needed so i have to declare a destrcutor
but c# don't allow struct
to have destrcutor
or to override 'Finalize' method and if the such variable of type IntPtr<T>
goes out of scope the destruction take place but the GCHandle
won't be free.
UPDATE
As an example of this class usage, suppose we going to interpo COAUTHIDENTITY
and COAUTHINFO
from COM
, here what it will look like:
[StructLayout(LayoutKind.Sequential)]
struct COAUTHIDENTITY
{
[MarshalAs(UnmanagedType.LPWStr)] string User;
uint UserLength;
[MarshalAs(UnmanagedType.LPWStr)] string Domain;
uint DomainLength;
[Mar开发者_Python百科shalAs(UnmanagedType.LPWStr)] string Password;
uint PasswordLength;
uint Flags;
}
[StructLayout(LayoutKind.Sequential)]
struct COAUTHINFO
{
uint dwAuthnSvc;
uint dwAuthzSvc;
[MarshalAs(UnmanagedType.LPWStr)] string pwszServerPrincName;
uint dwAuthnLevel;
uint dwImpersonationLevel;
IntPtr<COAUTHIDENTITY> pAuthIdentityData;
uint dwCapabilities;
}
Instead to make pAuthIdentityData
an IntPtr
and use Marshal
member functions to get object of type COAUTHIDENTITY
, IntPtr<T>
will make it more simple.
The question is: where should i write the code to free GCHandle
when the IntPtr<T>
is released?
You're reinventing the wheel. Look at the SafeHandle class. Use an existing descendant or create your own descendant.
精彩评论