2011-02-04 12 views
9

Intento Lazy < SelectList> para el almacenamiento en caché vago de cualquier información de búsqueda en mi proyecto ASP.NET MVC. Pero no puedo obligar al objeto Lazy a volver a cargar los datos de búsqueda cuando se modifique.Cómo forzar al objeto Lazy <T> a crear/volver a crear el valor?

Creo clase derivada como el siguiente código. Descubrí que Lazy < T> usa la propiedad IsValueCreated para mantener el estado actual. Sin embargo, en el método MappingFunc no puedo cambiar el valor de IsValueCreated porque es un método estático.

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); 
     }; 
    } 
} 

Utilizo el siguiente código para llamar a esta función. Pero siempre crea un nuevo valor porque el valor de IsValueCreated siempre es falso.

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

Posible duplicado de http://stackoverflow.com/questions/5961252/reset-system-lazy/ – Olmo

Respuesta

10

Al cabo de varias horas para buscar & pruebas, creo que es imposible restablecer el estado del objeto perezoso. Pero puedo crear un contenedor para manejar este problema. La clase contenedora contiene un objeto perezoso y un objeto necesario para crear un nuevo objeto perezoso. El código debería ser así.

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); 
     }; 
    } 
} 

El código anterior nos permite restablecer el estado del objeto para forzarlo a recuperar nuevos datos para la función definida.

Después de eso, trato de utilizar el método anterior para almacenar en caché el objeto SelectList en ASP.NET MVC. Pero siempre recupera datos nuevos de la base de datos porque SelectList contendrá el objeto IEnumerable en lugar de datos reales del objeto. Entonces, resuelvo el problema enumerando los datos en la lista de objetos temporales como la siguiente clase.

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. Todos los códigos fuente son parte de mi marco Higgs RIA disponible en el sitio web de Codeplex.

LazyCache.cs | LazyList.cs

Cuestiones relacionadas