创建一个完整的只读对象列表的最佳方法

3
我正在使用 C# 4.0Asp.Net。我在创建自定义缓存时遇到了一个问题,关于如何正确构建一个只读结构体。
详细信息(概述):
我的 CacheManager 类(单例)作为参数使用现有的 MemoryCache 类的实例,并包装了一些有用的方法来处理一些附加的东西,例如在我的自定义缓存中管理对象生命周期等。
该 Manager 处理一个简单的 CachableObject,它包含三个变量:
- object - DateTime - int (duration)
简而言之,我的自定义缓存管理器将对象存储一段时间以保护数据库免受频繁的大型查询的影响。
最近,我尝试过:
- 从缓存中获取一个对象(即存储在键“-MyList”下) - 将其转换回复杂对象列表 - 对每个复杂对象的属性内容进行翻译 - 将新翻译的对象列表重新存储在缓存中(在另一个键“-MyTranslatedList”下)
问题:
在测试期间,我发现缓存中存储的两个列表(原始和翻译后的列表)都指向相同的基础对象。因此,一旦翻译,这些对象实际上在两个列表中都被翻译了。
由于每个列表只引用对象,这是完全正常的行为和我的一个愚蠢错误。
问题如下:
正如您现在可以轻松地猜到的那样,我想保护自己和我的单例用户免受这种错误的影响。
我想要插入(或存储或获取)任何类型的对象(或复杂对象列表),以便通过缓存获取的任何人都不能修改它们。我希望我的缓存中的数据是只读的(并且是深度只读的),以避免出现这种问题。我希望任何人在开始使用存储在缓存中的数据之前都必须创建一个深层副本(或更好地说,获取一个)。
到目前为止,我尝试了以下方法:
我尝试将对象设置为只读,但没有达到预期效果。
由于我经常存储复杂对象列表,因此我发现 AsReadOnly 方法返回一个 IReadOnlyCollection,虽然这可以防止我更改列表(添加、删除),但它并不保护列表中的对象。
希望我的解释有些清楚:)
有没有一种简洁的方法来处理这种情况呢?

不,如果某人拥有一个对象的引用,那么没有办法防止他更改该对象。如果您真的不想更改这些对象,可以将它们制作为ICloneable或为它们提供只读接口。 - JustSomeGuy
你可以使用不可变集合 - Sameer
@Sameer 谢谢你的回答, Sameer。到目前为止,从我的理解来看,不可变集合提供对一个不会改变的列表的线程安全访问。它并不保证列表中的元素不会改变……你知道我的意思吗? - Andy M
@Spo1ler 感谢您的回答Spo1ler。嗯,问题在于,由于我正在将随机对象放入我的缓存中,我无法更改所有对象使它们成为ICloneable。这有意义吗? - Andy M
1个回答

0
我会创建一个属性是只读的类。
class ReadonlyClass
{
    private string p1;
    private int p2;

    public ReadonlyClass(string property1, int property2)
    {
        p1 = property1;
        p2 = property2;
    }

    public string Property1
    {
        get { return p1; }
    }

    public int Property2
    {
        get { return p2; }
    }
}

如果属性是对象/其他类,则应实现一个克隆函数,该函数返回对象的副本。上述类的克隆函数如下所示:
    public ReadonlyClass clone()
    {
        return new ReadonlyClass(p1, p2);
    }

此致
敬礼
汉斯·米林


嗨,汉斯,谢谢你的答案。问题在于,我的缓存中可以有任何类型的对象。它还包括在我的源代码之外构建的对象,例如从查询返回的实体框架对象。 - Andy M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接