2

I am trying to save an Object which implements an Interface say IInterface.

private PersistentDictionary<string, IInterface> Object = new PersistentDictionary<string, IInterface>(Environment.CurrentDirectory + @"\Object");

Since many classes implement the same interface(all of which need to cached), for a generic approach I want to store an Object of type IInterface in the dictionary.
So that anywhere I can pull out that object type cast it as IInterface and use that object's internal implementation of methods etc..

But, as soon as the Esent cache is initialized it throws this error:
Not supported for SetColumn
Parameter name: TColumn
Actual value was IInterface.

I have tried to not use XmlSerializer to do the same but is unable to deserialize an Interface type.Also, [Serializable] attribute cannot be used on top of a Interface, so I am stuck.

I have also tried to make all the implementations(classes) of the Interface as [Serializable] as a dying attempt but to no use.

Does any one know a way out ? Thanks in advance !!!

SutharMonil
  • 78
  • 3
  • 19

2 Answers2

5

The only reason that only structs are supported (as well as some basic immutable classes such as string) is that the PersistentDictionary is meant to be a drop-in replacement for Dictionary, SortedDictionary and other similar classes.

Suppose I have the following code:

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);

The output in this case would be 2. But if I'd used the PersistentDictionary instead of the regular one, the output would be 1. The class was created with value 1, and then changed after it was added to the dictionary. Since a class is a reference type, when we retrieve the item from the dictionary, we will also have the changed data.

Since the PersistentDictionary writes the data to disk, it cannot really handle reference types this way. Serializing it, and writing it to disk is essentially the same as treating the object as a value type (an entire copy is made).

Because it's intended to be used instead of the standard dictionaries, and the fact that it cannot handle reference types with complete transparency, the developers instead opted to support only structs, because structs are value types already.

However, if you're aware of this limitation and promise to be careful not to fall into this trap, you can allow it to serialize classes quite easily. Just download the source code and compile your own version of the EsentCollections library. The only change you need to make to it is to change this line:

if (!(type.IsValueType && type.IsSerializable))

to this:

if (!type.IsSerializable)

This will allow classes to be written to the PersistentDictionary as well, provided that it's Serializable, and its members are Serializable as well. A huge benefit is that it will also allow you to store arrays in there this way. All you have to keep in mind is that it's not a real dictionary, therefore when you write an object to it, it will store a copy of the object. Therefore, updating any of your object's members after adding them to the PersistentDictionary will not update the copy in the dictionary automatically as well, you'd need to remember to update it manually.

Cedric Mamo
  • 1,724
  • 2
  • 18
  • 33
  • How can i download the source? I want to follow your advice – NirMH Jul 10 '18 at 08:53
  • I just tried this it does not work. It blows up in the constructor or the ColumnConverter. The underlying type is not available in the map of method names allowed and even if it were the CreateSetColumnDelegate() method fails. (I would put the code in here but stack overflow does not seem to like that in the comment section. Or I have no idea how to make it work) – Noel Oct 08 '20 at 18:10
1

PersistentDictionary can only store value-structs and a very limited subset of classes (string, Uri, IPAddress). Take a look at ColumnConverter.cs, at private static bool IsSerializable(Type type) for the full restrictions. You'd be hitting the typeinfo.IsValueType() restriction.

By the way, you can also try posting questions about PersistentDictionary at http://managedesent.codeplex.com/discussions .

-martin

Martin Chisholm
  • 461
  • 2
  • 6