我正在尝试保存一个实现接口的对象,说IInterface。
private PersistentDictionary<string, IInterface> Object = new PersistentDictionary<string, IInterface>(Environment.CurrentDirectory + @"Object");
由于许多类实现相同的接口(所有这些都需要缓存),对于泛型方法,我希望在字典中存储IInterface类型的Object。
这样我就可以把对象类型转换为IInterface并使用该对象的内部实现方法等。
但是,一旦初始化了Esent缓存,它就会抛出这个错误:
SetColumn
不支持参数名称:TColumn
实际值为IInterface。
我试图不使用XmlSerializer
做同样的事情,但无法反序列化接口类型。此外,[Serializable]
属性不能在接口上使用,所以我卡住了。
我还试图使接口的所有实现(类)作为[Serializable]
作为一个垂死的尝试,但没有使用。
只支持结构体(以及一些基本的不可变的类,如string)的唯一原因是PersistentDictionary
意味着是Dictionary
, SortedDictionary
和其他类似类的临时替代品。
class MyClass
{
int val;
}
.
.
.
var dict = new Dictionary<int,MyClass>();
var x = new MyClass();
x.val = 1;
dict.Add(0,x);
x.val = 2;
var y = dict[0];
Console.WriteLine(y.val);
本例中的输出将是2。但是如果我使用PersistentDictionary
而不是常规的,输出将是1。类的创建值为1,然后在将其添加到字典后进行更改。由于类是引用类型,因此当从字典中检索项时,也将获得更改后的数据。
由于PersistentDictionary
将数据写入磁盘,因此它不能真正以这种方式处理引用类型。序列化对象并将其写入磁盘本质上与将对象作为值类型处理(生成整个副本)相同。
因为它是用来代替标准字典的,而且它不能完全透明地处理引用类型,所以开发人员选择只支持结构体,因为结构体已经是值类型了。
然而,如果您意识到这个限制并承诺小心不落入这个陷阱,您可以允许它很容易地序列化类。只需下载源代码并编译您自己版本的EsentCollections库。您唯一需要做的更改是更改这一行:
if (!(type.IsValueType && type.IsSerializable))
:
if (!type.IsSerializable)
这将允许类也写入PersistentDictionary
,前提是它是可序列化的,并且它的成员也是可序列化的。一个巨大的好处是,它还允许您以这种方式在那里存储数组。你所要记住的是,它不是一个真正的字典,因此当你向它写入一个对象时,它将存储对象的副本。因此,在将对象的任何成员添加到PersistentDictionary
之后更新它们将不会自动更新字典中的副本,您需要记住手动更新它。
PersistentDictionary只能存储值结构和非常有限的类子集(string, Uri, IPAddress)。请查看ColumnConverter.cs,在private static bool IsSerializable(Type Type)中查看完整的限制。你会碰到typeinfo.IsValueType()限制。
顺便说一下,您也可以尝试在http://managedesent.codeplex.com/discussions上发布关于PersistentDictionary的问题。
再也