2011-02-04 9 views
9

私はASP.NET MVCプロジェクトのルックアップデータを怠惰にキャッシュするために、SelectList>を試してみてください。<しかし、Lazyオブジェクトを変更したときにルックアップデータを強制的にリロードすることはできません。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

答えて

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。すべてのソースコードは、CodeplexのWebサイトで入手できるHiggs RIAフレームワークの一部です。

LazyCache.cs | LazyList.cs