You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
106 lines
3.2 KiB
106 lines
3.2 KiB
#if NET20 || NET30 || NET35 || NET40 || !NET_4_6 |
|
|
|
using System.Runtime.InteropServices; |
|
using System.Runtime.Serialization; |
|
//using System.Security.Permissions; |
|
|
|
namespace System |
|
{ |
|
[Serializable] |
|
public sealed class WeakReference<T> : ISerializable |
|
where T : class |
|
{ |
|
private readonly bool _trackResurrection; |
|
private GCHandle _handle; |
|
|
|
public WeakReference(T target) |
|
: this(target, false) |
|
{ |
|
//Empty |
|
} |
|
|
|
public WeakReference(T target, bool trackResurrection) |
|
{ |
|
_trackResurrection = trackResurrection; |
|
SetTarget(target); |
|
} |
|
|
|
internal WeakReference(SerializationInfo info, StreamingContext context) |
|
{ |
|
if (info == null) |
|
{ |
|
throw new ArgumentNullException("info"); |
|
} |
|
var value = (T)info.GetValue("TrackedObject", typeof(T)); |
|
_trackResurrection = info.GetBoolean("TrackResurrection"); |
|
SetTarget(value); |
|
} |
|
|
|
//[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] |
|
public void GetObjectData(SerializationInfo info, StreamingContext context) |
|
{ |
|
if (info == null) |
|
{ |
|
throw new ArgumentNullException("info"); |
|
} |
|
T value; |
|
TryGetTarget(out value); |
|
info.AddValue("TrackedObject", value, typeof(T)); |
|
info.AddValue("TrackResurrection", _trackResurrection); |
|
} |
|
|
|
//[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] |
|
public void SetTarget(T value) |
|
{ |
|
var oldHandle = _handle; |
|
_handle = GetNewHandle(value, _trackResurrection); |
|
if (oldHandle.IsAllocated) |
|
{ |
|
oldHandle.Free(); |
|
try |
|
{ |
|
oldHandle.Free(); |
|
} |
|
catch (InvalidOperationException exception) |
|
{ |
|
// The handle was freed or never initialized. |
|
// Nothing to do. |
|
GC.KeepAlive(exception); |
|
} |
|
} |
|
_handle = GetNewHandle(value, _trackResurrection); |
|
} |
|
|
|
//[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] |
|
public bool TryGetTarget(out T target) |
|
{ |
|
target = default(T); |
|
if (!_handle.IsAllocated) |
|
{ |
|
return false; |
|
} |
|
try |
|
{ |
|
var obj = _handle.Target; |
|
if (obj == null) |
|
{ |
|
return false; |
|
} |
|
target = obj as T; |
|
return true; |
|
} |
|
catch (InvalidOperationException) |
|
{ |
|
return false; |
|
} |
|
} |
|
|
|
//[SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)] |
|
private GCHandle GetNewHandle(T value, bool trackResurrection) |
|
{ |
|
return GCHandle.Alloc(value, trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak); |
|
} |
|
} |
|
} |
|
|
|
#endif |