事情是酱紫的
在当前项目中,用到了微软的unity依赖注入工具,原先项目代码是跑在WEB上的,从Kigg复制过来的代码自带了PerRequest级别的对象生命周期管理,结合Entity Framework和UnitOfWork、Repository模式,用起来没什么问题。可是后来,加了一个C/S结构的服务程序,为了代码复用,我把用于WEB上的程序集加了进来。这样一来,原先的PerRequest级别的对象生命周期管理肯定是不能用了,怎么办呢?我草率的把ObjectContext对象的生命周期搞成了singleton,可是跑了一段时间我就发现问题:服务器的数据库写是在多线程方式下运行的,而ObjectContest不是线程安全的,这显然不行。于是我想到,自己定义一个类似于PerRequest级别的生命周期管理--PerThread。
PerThread对象生命周期管理
听名字就知道,这个对象生命周期管理是为同一个线程里的类型注入同一个对象实例的管理方式。因为手头有PerRequest的代码,所以模仿着写一个还是很容易的。我直接上代码。要是代码或想法有问题还请提出,平时写BS为主,对线程不熟。
1 /// <summary> 2 /// 线程级别生命周期 3 /// </summary> 4 public class UnityPerThreadLifetimeManager : LifetimeManager 5 { 6 private Thread _thread; 7 public UnityPerThreadLifetimeManager(Thread thread) 8 { 9 _thread = thread; 10 } 11 public UnityPerThreadLifetimeManager() 12 : this(Thread.CurrentThread) 13 { 14 15 } 16 public override object GetValue() 17 { 18 IDictionary<UnityPerThreadLifetimeManager, object> backingStore = BackingStore; 19 return backingStore.ContainsKey(this) ? backingStore[this] : null; 20 } 21 22 public override void RemoveValue() 23 { 24 throw new NotImplementedException(); 25 } 26 27 public override void SetValue(object newValue) 28 { 29 IDictionary<UnityPerThreadLifetimeManager, object> backingStore = BackingStore; 30 31 if (backingStore.ContainsKey(this)) 32 { 33 object oldValue = backingStore[this]; 34 35 if (!ReferenceEquals(newValue, oldValue)) 36 { 37 IDisposable disposable = oldValue as IDisposable; 38 39 if (disposable != null) 40 { 41 disposable.Dispose(); 42 } 43 44 if (newValue == null) 45 { 46 backingStore.Remove(this); 47 } 48 else 49 { 50 backingStore[this] = newValue; 51 } 52 } 53 } 54 else 55 { 56 if (newValue != null) 57 { 58 backingStore.Add(this, newValue); 59 } 60 } 61 } 62 63 private IDictionary<UnityPerThreadLifetimeManager, object> BackingStore 64 { 65 get 66 { 67 _thread = (Thread.CurrentThread != null) ? Thread.CurrentThread : _thread; 68 69 return UnityPerThreadLifetimeManager.GetInstances(_thread); 70 } 71 } 72 73 private static IDictionary<Thread, IDictionary<UnityPerThreadLifetimeManager, object>> totalStore = new Dictionary<Thread, IDictionary<UnityPerThreadLifetimeManager, object>>(); 74 75 internal static IDictionary<UnityPerThreadLifetimeManager, object> GetInstances(Thread thread) 76 { 77 IDictionary<UnityPerThreadLifetimeManager, object> instances; 78 79 if (totalStore.ContainsKey (thread )) 80 { 81 instances = (IDictionary<UnityPerThreadLifetimeManager, object>)totalStore[thread ]; 82 } 83 else 84 { 85 lock (totalStore) 86 { 87 //删除已经结束的线程 88 IList<Thread> threads = totalStore.Keys.ToList(); 89 for (int i = totalStore.Count - 1; i >= 0; i--) 90 { 91 Thread item = threads[i]; 92 if (item.IsAlive == false) 93 { 94 IDictionary<UnityPerThreadLifetimeManager, object> removeInstances = (IDictionary<UnityPerThreadLifetimeManager, object>)totalStore[item]; 95 foreach (var ins in removeInstances ) 96 { 97 IDisposable dispose = ins.Value as IDisposable; 98 if (dispose != null) 99 dispose.Dispose(); 100 } 101 totalStore.Remove(item); 102 } 103 } 104 105 if (totalStore.ContainsKey(thread)) 106 { 107 instances = (IDictionary<UnityPerThreadLifetimeManager, object>)totalStore[thread ]; 108 } 109 else 110 { 111 instances = new Dictionary<UnityPerThreadLifetimeManager, object>(); 112 totalStore.Add(thread, instances); 113 } 114 } 115 } 116 117 return instances; 118 } 119 }