NativeObjectCache.cs
4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Linq;
namespace Helper
{
public static class NativeObjectCache
{
private static object _lock = new object();
private static Dictionary<Type, Dictionary<IntPtr, WeakReference>> _objectCache = new Dictionary<Type, Dictionary<IntPtr, WeakReference>>();
public static void AddObject<T>(IntPtr nativePtr, T obj) where T : class
{
lock (_lock)
{
Dictionary<IntPtr, WeakReference> objCache = null;
if (!_objectCache.TryGetValue(typeof(T), out objCache) || objCache == null)
{
objCache = new Dictionary<IntPtr, WeakReference>();
_objectCache[typeof(T)] = objCache;
}
objCache[nativePtr] = new WeakReference(obj);
}
}
public static void Flush()
{
lock(_lock)
{
foreach (var byType in _objectCache.ToArray())
{
foreach(var kvp in byType.Value.ToArray())
{
IDisposable disp = kvp.Value.Target as IDisposable;
if(disp != null)
{
disp.Dispose();
}
}
}
}
}
public static void RemoveObject<T>(IntPtr nativePtr)
{
lock (_lock)
{
Dictionary<IntPtr, WeakReference> objCache = null;
if (!_objectCache.TryGetValue(typeof(T), out objCache) || objCache == null)
{
objCache = new Dictionary<IntPtr, WeakReference>();
_objectCache[typeof(T)] = objCache;
}
if (objCache.ContainsKey(nativePtr))
{
objCache.Remove(nativePtr);
}
}
}
public static T GetObject<T>(IntPtr nativePtr) where T : class
{
lock (_lock)
{
Dictionary<IntPtr, WeakReference> objCache = null;
if (!_objectCache.TryGetValue(typeof(T), out objCache) || objCache == null)
{
objCache = new Dictionary<IntPtr, WeakReference>();
_objectCache[typeof(T)] = objCache;
}
WeakReference reference = null;
if (objCache.TryGetValue(nativePtr, out reference))
{
if (reference != null)
{
T obj = reference.Target as T;
if (obj != null)
{
return (T)obj;
}
}
}
return null;
}
}
public static T CreateOrGetObject<T>(IntPtr nativePtr, Func<System.IntPtr,T> create) where T : class
{
T outputValue = null;
lock (_lock)
{
Dictionary<IntPtr, WeakReference> objCache = null;
if (!_objectCache.TryGetValue(typeof(T), out objCache) || objCache == null)
{
objCache = new Dictionary<IntPtr, WeakReference>();
_objectCache[typeof(T)] = objCache;
}
WeakReference reference = null;
if (objCache.TryGetValue(nativePtr, out reference))
{
if ((reference != null) && reference.IsAlive)
{
outputValue = reference.Target as T;
}
}
if (outputValue == null)
{
if (create != null)
{
outputValue = create(nativePtr);
objCache[nativePtr] = new WeakReference(outputValue);
}
else if(typeof(T) == typeof(System.Object))
{
//T is an object, so lets just pass back our IntPtr, which is an object.
outputValue = (T)(System.Object)nativePtr;
}
}
}
return outputValue;
}
}
}