Asp.net mvc 3 MVC 3:从缓存返回不可变对象

Asp.net mvc 3 MVC 3:从缓存返回不可变对象,asp.net-mvc-3,c#-4.0,caching,Asp.net Mvc 3,C# 4.0,Caching,我有一个MVC3应用程序,它调用外部API来获取数据。API返回XML,然后将其序列化为对象。其中一些对象在一天中不会改变,所以我缓存它们以减少开销。我的问题是,如果我从缓存中获取一个项目并对其进行操作,它也会更改缓存的值。我假设这是因为只返回对缓存项的引用。我正在使用System.Web.HttpRuntime.Cache缓存对象。有没有办法将缓存中的项作为不可变对象返回?或者轻松返回对象的克隆?我曾尝试将缓存的值反序列化回XML,然后将其序列化为一个新对象,尽管这样做可行,但会增加大量开销,

我有一个MVC3应用程序,它调用外部API来获取数据。API返回XML,然后将其序列化为对象。其中一些对象在一天中不会改变,所以我缓存它们以减少开销。我的问题是,如果我从缓存中获取一个项目并对其进行操作,它也会更改缓存的值。我假设这是因为只返回对缓存项的引用。我正在使用System.Web.HttpRuntime.Cache缓存对象。有没有办法将缓存中的项作为不可变对象返回?或者轻松返回对象的克隆?我曾尝试将缓存的值反序列化回XML,然后将其序列化为一个新对象,尽管这样做可行,但会增加大量开销,并导致站点在负载下运行得非常糟糕。我可以为每个项目实现ICloneable,但是接下来我必须为我的每个类编写一个深度克隆方法,这将花费很多时间,并且可能与序列化有相同的开销问题。我想知道有没有更快的办法

假设我缓存了一个人员列表。如果我这样做:

var people = Cache.Get<List<Person>>("people");
people.Remove(p => p.LastName != "Smith");
return View(people);
var people=Cache.Get(“人”);
删除(p=>p.LastName!=“Smith”);
返回视图(人);
这将从视图和缓存列表中删除列表中姓氏不是Smith的所有人员。该物品的未来进货将只返回史密斯

我可以通过以下方式解决这个问题:

var people = Cache.Get<List<Person>>("people");
var viewlist = people.Where(p => p.LastName == "Smith").ToList();
return View(viewlist);
var people=Cache.Get(“人”);
var viewlist=people.Where(p=>p.LastName==“Smith”).ToList();
返回视图(视图列表);
这不会影响缓存的值。显然,我可以在代码中的任何地方都这样做,但是考虑到缓存的项目数量,我必须确保每次都这样做。如果我试图编辑从缓存中获取的对象,那么让代码抛出编译时(甚至运行时)错误会更好

我的缓存方法:

static object lockobj = new object();
public static T Get<T>(string index) //where T : new()
{
    T data;
    lock (lockobj)
    {
        data = (T)_cache[index];
    }
    return data;
}

public static T CacheInsert<T>(T obj, string index, CacheDependency dependencies,
        DateTime absoluteExpiration, TimeSpan slidingExpiration,
        CacheItemPriority priority, CacheItemRemovedCallback callback)
{
    T data;
    lock (lockobj)
    {
        data = (T)_cache[index];
        if (data == null)
        {
            _cache.Insert(index, obj, dependencies, absoluteExpiration, slidingExpiration, priority, callback);
            data = obj;
        }
    }
    return data;
}
static object lockobj=new object();
公共静态T Get(字符串索引)//其中T:new()
{
T数据;
锁(lockobj)
{
数据=(T)u缓存[索引];
}
返回数据;
}
公共静态缓存插入(T obj、字符串索引、缓存依赖项、,
日期时间绝对过期,时间跨度滑动过期,
CacheItemPriority,CacheItemRemovedCallback(回调)
{
T数据;
锁(lockobj)
{
数据=(T)u缓存[索引];
如果(数据==null)
{
_插入(索引、对象、依赖项、绝对过期、滑动过期、优先级、回调);
数据=obj;
}
}
返回数据;
}

这是因为您使用的列表集合类型。列表提供对当前集合的引用。如果不想修改缓存集合,则必须复制集合并运行筛选器。或者从缓存返回ienumarable,该缓存将不允许修改当前集合并执行必要的操作,如筛选

如果你需要它的例子,请让我知道