zoukankan      html  css  js  c++  java
  • 实现 对象在内存中的引用一致性 之第一步

    • 原委

      废话不要,他们都该删。

      虽然写了个 基于数据库的代码生成器 与大家分享,但并不擅长数据库开发;相反,面向对象才是我的爱。
      多年的酝酿让我收获良多,直觉这是个令人激动的开发模式。

      或许是因为高中学历吧,我的思想还是朴素的:在实施软件开发时,第一反应是对象而不是数据库。

    • 实施

      朴素的思想让人选择朴素的视角,一种朴素的视角看到的是:

      Assert.AreSame(employee1.Department, employee2.Department);

      或许更适用些的断言是:

      if (model1.Id == model2.Id)
          Assert.AreSame(model1, model2);

      实现此断言即是实现 对象在内存中的唯一性,不过我还是觉得叫 对象在内存中的引用一致性 贴切点;
      开始实现吧。

      假设我们已经分析过业务了,那接下来的第一步当然是业务模型的建立了,这一步很是顺其自然且乏味地就能 下载到结果
      Northwind1

      紧接上一步,我们发现了一个显眼的问题:大值属性。
      这真是个好问题,让人莫名地开心起来。

      这个问题的解决就是我们第二步需要做的了,不过还是妙手偶得之地就能 下载到结果
      CachedProperties

      实现的要点在这里:

      using System;
      using System.Runtime.Caching;
      
      namespace Codesir.Net.Identical
      {
          /// <summary>
          /// 实现软引用,同时具备 缓存的长时效 和 弱引用的一致性 优点。
          /// </summary>
          public class CachedWeakReference<T>
              where T : class
          {
              static MemoryCache DefaultMemoryCache = MemoryCache.Default;
              static CacheItemPolicy DefaultCacheItemPolicy = new CacheItemPolicy { SlidingExpiration = TimeSpan.FromMinutes(20) };
      
              WeakReference weakReference;
              MemoryCache memoryCache;
              CacheItemPolicy cacheItemPolicy;
              string cacheKey;
      
              /// <summary>
              /// 使用指定的对象初始化一个软引用实例。
              /// </summary>
              /// <param name="target">要缓存并跟踪的对象。</param>
              public CachedWeakReference(T target)
                  : this(target, CachedWeakReference<T>.DefaultMemoryCache, CachedWeakReference<T>.DefaultCacheItemPolicy)
              { }
              /// <summary>
              /// 使用指定的对象和缓存选项初始化一个软引用实例。
              /// </summary>
              /// <param name="target">要缓存并跟踪的对象。</param>
              /// <param name="memoryCache">要跟踪的对象加入到的内存缓存。</param>
              /// <param name="cacheItemPolicy">要跟踪的对象的缓存过期策略。</param>
              public CachedWeakReference(T target, MemoryCache memoryCache, CacheItemPolicy cacheItemPolicy)
              {
                  if (target == null) throw new ArgumentNullException("target");
                  if (memoryCache == null) throw new ArgumentNullException("memoryCache");
                  if (cacheItemPolicy == null) throw new ArgumentNullException("cacheItemPolicy");
      
                  this.weakReference = new WeakReference(target);
                  this.memoryCache = memoryCache;
                  this.cacheItemPolicy = cacheItemPolicy;
                  this.cacheKey = Guid.NewGuid().ToString();
      
                  this.memoryCache.Set(this.cacheKey, target, this.cacheItemPolicy);
              }
      
              /// <summary>
              /// 获取或设置当前软引用实例所引用的对象。
              /// </summary>
              public T Target
              {
                  get
                  {
                      T target = null;
      
                      T targetFromCache = this.memoryCache.Get(this.cacheKey) as T;
                      if (targetFromCache == null) //如果已从内存缓存移出
                      {
                          T targetByReference = this.weakReference.Target as T;
                          if (targetByReference != null) //但引用依然有效
                          {
                              this.memoryCache.Set(this.cacheKey, targetByReference, this.cacheItemPolicy); //则继续受内存缓存管理
                              target = targetByReference;
                          }
                      }
                      else
                      {
                          target = targetFromCache;
                      }
      
                      return target;
                  }
                  set
                  {
                      if (value == null) throw new ArgumentNullException("value");
      
                      this.weakReference.Target = value;
                      this.memoryCache.Set(this.cacheKey, value, this.cacheItemPolicy);
                  }
              }
          }
      }

      上段代码看上去还行,不过接下来的这个就狗便了,不知有没好心人优化下,在 CachedWeakReferenceProperty 里:

      /// <summary>
      /// 获取或设置属性值,值的重建已线程安全。
      /// </summary>
      public TProperty Value
      {
          get
          {
              TProperty value = null;
      
              if (this.isNull.HasValue && !this.isNull.Value && this.weakReference != null)
                  value = this.weakReference.Target;
      
              if (this.owner.HasPersisted //只有已持久化才可能被重建
                  && (this.isNull == null || (this.isNull.HasValue && this.isNull.Value && value == null))) //从未重建 或 已被回收 则需重建
              {
                  lock (this)
                  {
                      if (this.isNull == null || (this.isNull.HasValue && this.isNull.Value && this.weakReference.Target == null))
                      {
                          value = this.reconstructFunc();
      
                          this.isNull = value == null;
                          this.weakReference = value == null ? null : new CachedWeakReference<TProperty>(value);
                      }
                      else //双检失败是因为锁前线程已重建
                      {
                          if (this.weakReference != null)
                              value = this.weakReference.Target;
                      }
                  }
              }
      
              return value;
          }
          set
          {
              this.isNull = value == null;
              this.weakReference = value == null ? null : new CachedWeakReference<TProperty>(value);
          }
      }

      今天就分享到这吧,还有更多更让人开心的问题等着我们呢。

  • 相关阅读:
    二级域名配置
    环信框架-消息模块
    屏幕适配问题
    iOS-NSSession
    环信框架使用
    静态UITableView
    __weak存在的问题
    MVVM与MVC
    iOS通知与多线程
    block
  • 原文地址:https://www.cnblogs.com/JimHappy/p/3166484.html
Copyright © 2011-2022 走看看