asp.net-mvc - 如何强制 Lazy<T> 对象创建/重新创建值?

标签 asp.net-mvc c#-4.0 lazy-evaluation

我尝试使用 Lazy< SelectList > 来延迟缓存 ASP.NET MVC 项目中的任何查找数据。但我无法强制 Lazy 对象在更改时重新加载查找数据。

我创建派生类,如以下代码。我发现 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");

最佳答案

经过几个小时的搜索和测试,我认为不可能重置惰性对象的状态。但我可以创建包装器来处理这个问题。包装类包含惰性对象和创建新惰性对象所需的对象。代码应该是这样的。

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

关于asp.net-mvc - 如何强制 Lazy<T> 对象创建/重新创建值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4897405/

相关文章:

c# - 如何知道用户是否可以读取和列出目录中的文件

asp.net-mvc-3 - 在 LINQ 查询中调用方法

c# - List<[]> 中的 Excel 数据输入速度很慢,是否有更好的算法设计?

hibernate - 更新 JPA-Hibernate 实体而不从数据库中选择它

python - Python 中的内存交换时间

exception - 如果 thunk 导致异常,异常是否会保留为 thunk 的结果?

jquery - 将部分 View 加载到同一页面上的 div 标签中

asp.net-mvc - 如何从 MVC Controller 返回 Json 对象以查看

c# - 如何在不中断所有异常的情况下使 VS 在异步任务中中断异常?

c# - asp.net mvc @Html.CheckBoxFor