1 // ==++== 2 // 3 // Copyright (c) Microsoft Corporation. All rights reserved. 4 // 5 // ==--== 6 /*============================================================ 7 ** 8 ** Class: WeakReference<T> 9 ** 10 ** Purpose: A wrapper for establishing a WeakReference to a generic type. 11 ** 12 ===========================================================*/ 13 namespace System 14 { 15 using System; 16 using System.Runtime.Serialization; 17 using System.Security; 18 using System.Runtime; 19 using System.Runtime.CompilerServices; 20 using System.Runtime.Versioning; 21 using System.Diagnostics.Contracts; 22 23 [Serializable] 24 // This class is sealed to mitigate security issues caused by Object::MemberwiseClone. 25 public sealed class WeakReference<T> : ISerializable where T : class 26 { 27 // If you fix bugs here, please fix them in WeakReference at the same time. 28 29 // This field is not a regular GC handle. It can have a special values that are used to prevent ----s between setting the target and finalization. 30 internal IntPtr m_handle; 31 32 // Creates a new WeakReference that keeps track of target. 33 // Assumes a Short Weak Reference (ie TrackResurrection is false.) 34 // WeakReference(T target)35 public WeakReference(T target) 36 : this(target, false) 37 { 38 } 39 40 //Creates a new WeakReference that keeps track of target. 41 // WeakReference(T target, bool trackResurrection)42 public WeakReference(T target, bool trackResurrection) 43 { 44 Create(target, trackResurrection); 45 } 46 WeakReference(SerializationInfo info, StreamingContext context)47 internal WeakReference(SerializationInfo info, StreamingContext context) 48 { 49 if (info == null) { 50 throw new ArgumentNullException("info"); 51 } 52 Contract.EndContractBlock(); 53 54 T target = (T)info.GetValue("TrackedObject", typeof(T)); 55 bool trackResurrection = info.GetBoolean("TrackResurrection"); 56 57 Create(target, trackResurrection); 58 } 59 60 // 61 // We are exposing TryGetTarget instead of a simple getter to avoid a common problem where people write incorrect code like: 62 // 63 // WeakReference ref = ...; 64 // if (ref.Target != null) 65 // DoSomething(ref.Target) 66 // 67 [MethodImplAttribute(MethodImplOptions.AggressiveInlining)] TryGetTarget(out T target)68 public bool TryGetTarget(out T target) 69 { 70 // Call the worker method that has more performant but less user friendly signature. 71 T o = this.Target; 72 target = o; 73 return o != null; 74 } 75 SetTarget(T target)76 public void SetTarget(T target) 77 { 78 this.Target = target; 79 } 80 81 // This is property for better debugging experience (VS debugger shows values of properties when you hover over the variables) 82 private extern T Target 83 { 84 [ResourceExposure(ResourceScope.None)] 85 [MethodImplAttribute(MethodImplOptions.InternalCall)] 86 [SecuritySafeCritical] 87 get; 88 [ResourceExposure(ResourceScope.None)] 89 [MethodImplAttribute(MethodImplOptions.InternalCall)] 90 [SecuritySafeCritical] 91 set; 92 } 93 94 // Free all system resources associated with this reference. 95 // 96 // Note: The WeakReference<T> finalizer is not usually run, but 97 // treated specially in gc.cpp's ScanForFinalization 98 // This is needed for subclasses deriving from WeakReference<T>, however. 99 // Additionally, there may be some cases during shutdown when we run this finalizer. 100 [ResourceExposure(ResourceScope.None)] 101 [MethodImplAttribute(MethodImplOptions.InternalCall)] 102 [SecuritySafeCritical] ~WeakReference()103 extern ~WeakReference(); 104 105 [SecurityCritical] GetObjectData(SerializationInfo info, StreamingContext context)106 public void GetObjectData(SerializationInfo info, StreamingContext context) 107 { 108 if (info == null) { 109 throw new ArgumentNullException("info"); 110 } 111 Contract.EndContractBlock(); 112 113 info.AddValue("TrackedObject", this.Target, typeof(T)); 114 info.AddValue("TrackResurrection", IsTrackResurrection()); 115 } 116 117 [ResourceExposure(ResourceScope.None)] 118 [MethodImplAttribute(MethodImplOptions.InternalCall)] 119 [SecuritySafeCritical] Create(T target, bool trackResurrection)120 private extern void Create(T target, bool trackResurrection); 121 122 [ResourceExposure(ResourceScope.None)] 123 [MethodImplAttribute(MethodImplOptions.InternalCall)] 124 [SecuritySafeCritical] IsTrackResurrection()125 private extern bool IsTrackResurrection(); 126 } 127 } 128