После нескольких часов поиска и тестирования, я думаю, что невозможно сбросить состояние ленивого объекта. Но я могу создать оболочку для решения этой проблемы. Класс-обертка содержит ленивый объект и необходимый объект для создания нового ленивого объекта. Код должен быть таким.
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);
};
}
}
Приведенный выше код позволяет нам сбросить состояние объекта, чтобы заставить его извлекать новые данные для определенной функции.
После этого я пытаюсь использовать вышеуказанный метод для кэширования объекта SelectList в ASP.NET MVC. Но он всегда извлекает новое из базы данных, потому что 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