11using  System ; 
22using  System . Collections . Concurrent ; 
33using  System . Collections . Generic ; 
4- using  System . Runtime . CompilerServices ; 
54using  Rubberduck . VBEditor . SafeComWrappers . Abstract ; 
65
76#if DEBUG 
87using  System . Diagnostics ; 
98using  System . Linq ; 
10- using  System . Runtime . InteropServices ; 
119#endif
1210
1311namespace  Rubberduck . VBEditor . ComManagement 
1412{ 
15-     public  class  WeakComSafe  :  IComSafe 
13+     public  class  WeakComSafe  :  ComSafeBase 
1614    { 
1715        //We use weak references to allow the GC to reclaim RCWs earlier if possible. 
1816        private  readonly  ConcurrentDictionary < int ,  ( DateTime  insertTime ,  WeakReference < ISafeComWrapper >  weakRef ) >  _comWrapperCache  =  new  ConcurrentDictionary < int ,  ( DateTime ,  WeakReference < ISafeComWrapper > ) > ( ) ; 
1917
20- #if DEBUG 
21-         private  IEnumerable < string >  trace  =  null ; 
22- #endif
23- 
24-         public  void  Add ( ISafeComWrapper  comWrapper ) 
18+         public  override  void  Add ( ISafeComWrapper  comWrapper ) 
2519        { 
2620            if  ( comWrapper  !=  null ) 
2721            { 
2822#if DEBUG 
29-                 trace  =  GetStackTrace ( 3 ,  3 ) ; 
23+                 Trace  =  GetStackTrace ( 3 ,  3 ) ; 
3024#endif
3125                _comWrapperCache . AddOrUpdate ( 
3226                    GetComWrapperObjectHashCode ( comWrapper ) ,  
@@ -42,20 +36,13 @@ public void Add(ISafeComWrapper comWrapper)
4236
4337        } 
4438
45-         //We do not use GetHashCode because subclasses of SafeComWrapper<T> overwrite this method  
46-         //and we need to distinguish between individual instances. 
47-         private  int  GetComWrapperObjectHashCode ( ISafeComWrapper  comWrapper ) 
48-         { 
49-             return  RuntimeHelpers . GetHashCode ( comWrapper ) ; 
50-         } 
51- 
52-         public  bool  TryRemove ( ISafeComWrapper  comWrapper ) 
39+         public  override  bool  TryRemove ( ISafeComWrapper  comWrapper ) 
5340        { 
5441            return  ! _disposed  &&  comWrapper  !=  null  &&  _comWrapperCache . TryRemove ( GetComWrapperObjectHashCode ( comWrapper ) ,  out  _ ) ; 
5542        } 
5643
5744        private  bool  _disposed ; 
58-         public   void  Dispose ( ) 
45+         protected   override   void  Dispose ( bool   disposing ) 
5946        { 
6047            if  ( _disposed ) 
6148            { 
@@ -66,7 +53,7 @@ public void Dispose()
6653
6754            foreach  ( var  weakReference  in  _comWrapperCache . Values ) 
6855            { 
69-                 if ( weakReference . weakRef . TryGetTarget ( out  var  comWrapper ) ) 
56+                 if   ( weakReference . weakRef . TryGetTarget ( out  var  comWrapper ) ) 
7057                { 
7158                    comWrapper . Dispose ( ) ; 
7259                } 
@@ -76,75 +63,19 @@ public void Dispose()
7663        } 
7764
7865#if DEBUG 
79-         /// <summary> 
80-         /// Provide a serialized list of the COM Safe 
81-         /// to make it easy to analyze what is inside 
82-         /// the COM Safe at the different points of 
83-         /// the session's lifetime. 
84-         /// </summary> 
85-         public  void  Serialize ( ) 
86-         { 
87-             using  ( var  stream  =  System . IO . File . AppendText ( $ "comSafeOutput { DateTime . UtcNow : yyyyMMddhhmmss} .csv") ) 
88-             { 
89-                 stream . WriteLine ( "Ordinal\t Key\t COM Wrapper Type\t Wrapping Null?\t IUnknown Pointer Address\t Level 1\t Level 2\t Level 3" ) ; 
90-                 var  i  =  0 ; 
91-                 foreach  ( var  kvp  in  _comWrapperCache . OrderBy ( kvp =>  kvp . Value . insertTime ) ) 
92-                 { 
93-                     var  line  =  kvp . Value . weakRef . TryGetTarget ( out  var  target )  
94-                         ?  $ "{ i ++ } \t { kvp . Key } \t \" { target . GetType ( ) . FullName } \" \t \" { target . IsWrappingNullReference } \" \t \" { ( target . IsWrappingNullReference  ?  "null"  :  GetPtrAddress ( target . Target ) ) } \" \t \" { string . Join ( "\" \t \" " ,  trace ) } \" "  
95-                         :  $ "{ i ++ } \t { kvp . Key } \t \" null\" \t \" null\" \t \" null\" \t \" { string . Join ( "\" \t \" " ,  trace ) } \" "; 
96-                     stream . WriteLine ( line ) ; 
97-                 } 
98-             } 
99-         } 
100- 
101-         private  static   IEnumerable < string >  GetStackTrace ( int  frames ,  int  offset ) 
102-         { 
103-             var  list  =  new  List < string > ( ) ; 
104-             var  trace  =  new  StackTrace ( ) ; 
105-             if  ( ( trace . FrameCount  -  offset )  <  frames ) 
106-             { 
107-                 frames  =  ( trace . FrameCount  -  offset ) ; 
108-             } 
109- 
110-             for  ( var  i  =  1 ;  i  <=  frames ;  i ++ ) 
111-             { 
112-                 var  frame  =  trace . GetFrame ( i  +  offset ) ; 
113-                 var  typeName  =  frame . GetMethod ( ) . DeclaringType ? . FullName  ??  string . Empty ; 
114-                 var  methodName  =  frame . GetMethod ( ) . Name ; 
115- 
116-                 var  qualifiedName  =  $ "{ typeName } { ( typeName . Length  >  0  ?  "::"  :  string . Empty ) } { methodName } "; 
117-                 list . Add ( qualifiedName ) ; 
118-             } 
119-             return  list ; 
120-         } 
121- 
122-         private  static   string  GetPtrAddress ( object  target ) 
66+         protected  override  IDictionary < int ,  ISafeComWrapper >  GetWrappers ( ) 
12367        { 
124-             if  ( target  ==  null ) 
125-             { 
126-                 return  IntPtr . Zero . ToString ( ) ; 
127-             } 
128- 
129-             if  ( ! Marshal . IsComObject ( target ) ) 
130-             { 
131-                 return  "Not a COM object" ; 
132-             } 
133- 
134-             var  pointer  =  IntPtr . Zero ; 
135-             try 
136-             { 
137-                 pointer  =  Marshal . GetIUnknownForObject ( target ) ; 
138-             } 
139-             finally 
68+             var  dictionary  =  new  Dictionary < int ,  ISafeComWrapper > ( ) ; 
69+             foreach  ( var  kvp  in  _comWrapperCache . OrderBy ( kvp =>  kvp . Value . insertTime ) ) 
14070            { 
141-                 if  ( pointer   !=   IntPtr . Zero ) 
71+                 if  ( ! kvp . Value . weakRef . TryGetTarget ( out   var   target ) ) 
14272                { 
143-                     Marshal . Release ( pointer ) ; 
73+                     target   =   null ; 
14474                } 
75+                 dictionary . Add ( kvp . Key ,  target ) ;    
14576            } 
14677
147-             return  pointer . ToString ( ) ; 
78+             return  dictionary ; 
14879        } 
14980#endif
15081    } 
0 commit comments