zoukankan      html  css  js  c++  java
  • 为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     }
  • 相关阅读:
    数据库数据格式化之Kettle Spoon
    NopCommerce开源项目中很基础但是很实用的C# Helper方法
    oracle 两个逗号分割的字符串 如何判断是否其中有相同值
    MongoDB+MongoVUE安装及入门
    C#中Dictionary<TKey,TValue>排序方式
    kettle的基本介绍
    Kettle能做什么?
    oracle like 条件拼接
    loading加载和layer.js
    关于bootstrap的treeview不显示多选(复选框)的问题,以及联动选择的问题,外加多选后取值
  • 原文地址:https://www.cnblogs.com/xxfss2/p/2852514.html
Copyright © 2011-2022 走看看