2011-02-04 34 views
9

我嘗試懶惰< SelectList>用於在ASP.NET MVC項目中緩存任何查找數據。但是我不能強制Lazy對象在更改時重新加載查找數據。如何強制懶惰<T>對象創建/重新創建值?

我創建派生類,如下面的代碼。我發現Lazy < T>使用IsValueCreated屬性來保持當前狀態。但是,在MappingFunc方法中,我無法更改IsValueCreated的值,因爲它是靜態方法。

public class LazySelectList : Lazy<SelectList> 
{ 
    public LazySelectList(Func<LimeEntities, IEnumerable> initFn, string dataValueField, string dataTextField) 
     : base(MapingFunc(initFn, dataValueField, dataTextField)) 
    { 
    } 

    public new bool IsValueCreated { get; set; } 

    public static Func<SelectList> MapingFunc(Func<DbContext, IEnumerable> valueFactory, string dataValueField, string dataTextField) 
    { 
     return() => 
     { 
      var context = ObjectFactory.GetInstance<DbContext>(); 

      return new SelectList(valueFactory(context), dataValueField, dataTextField); 
     }; 
    } 
} 

我用下面的代碼調用這個函數。但它始終會創建新的值,因爲IsValueCreated值始終爲false。

LookupCache.DocTypeList = new LazySelectList(db => db.DocTypes.OrderBy(x => x.Name), "ID", "Name"); 
+1

http://stackoverflow.com/questions/5961252/reset-system-lazy/可能的重複 – Olmo 2011-06-06 17:01:55

回答

10

一個幾個小時搜索&測試後,我認爲這是不可能重置懶對象的狀態。但是我可以創建包裝來處理這個問題。包裝類包含用於創建新的惰性對象的惰性對象和必需對象。代碼應該是這樣的。

public class LazyCache<TSource, TModel> : IValue<TModel> 
{ 
    private Lazy<TModel> _lazyObj; 
    private readonly Func<TSource, TModel> _valueFactory; 

    protected LazyCache() 
    { 
     Reset(); 
    } 

    public LazyCache(Func<TSource, TModel> valueFactory) : this() 
    { 
     _valueFactory = valueFactory; 
    } 

    public void Reset() 
    { 
     _lazyObj = new Lazy<TModel>(MapingFunc()); 
    } 

    public TModel Value 
    { 
     get { return _lazyObj.Value; } 
    } 

    protected virtual Func<TModel> MapingFunc() 
    { 
     return() => 
     { 
      var context = ObjectFactory.GetInstance<TSource>(); 

      return _valueFactory(context); 
     }; 
    } 
} 

上面的代碼允許我們重置對象的狀態,迫使它檢索定義函數的新數據。

之後,我嘗試使用上面的方法來緩存ASP.NET MVC中的SelectList對象。但它始終從數據庫中檢索新的內容,因爲SelectList將包含IEnumerable對象而不是實際的對象數據。所以,我通過枚舉數據到像以下類的臨時對象列表來解決問題。

public class LazyList<TSource> : LazyCache<TSource, SelectList> 
{ 
    private readonly Func<TSource, IEnumerable> _valueFactory; 
    private readonly string _dataValueField; 
    private readonly string _dataTextField; 

    public LazyList(Func<TSource, IEnumerable> valueFactory, string dataValueField, string dataTextField) 
    { 
     _valueFactory = valueFactory; 
     _dataValueField = dataValueField; 
     _dataTextField = dataTextField; 
    } 

    protected override Func<SelectList> MapingFunc() 
    { 
     return() => 
     { 
      var context = ObjectFactory.GetInstance<TSource>(); 

      // Force to retrieve data from current IEnumerable to prevent lazy loading data that 
      // cause system always connect to database every time they generate data from selectlist. 
      var loop = _valueFactory(context).GetEnumerator(); 
      var tempList = new List<object>(); 

      while (loop.MoveNext()) 
      { 
       tempList.Add(loop.Current); 
      } 

      return new SelectList(tempList, _dataValueField, _dataTextField); 
     }; 
    } 
} 

PS。所有源代碼都是我的Higgs RIA框架的一部分,可在Codeplex網站上找到。

LazyCache.cs | LazyList.cs