为Unity添加线程级别的生命周期管理

事情是酱紫的

  在当前项目中,用到了微软的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     }
原文地址:https://www.cnblogs.com/xxfss2/p/2852514.html