Sometimes objects cannot be stored in db4o. For example because the objects have references to other parts of the system other where never intended to be stored. This is especially for objects from third party libraries.
Now the db4o object translators is a simple mechanism which allows you to manually handle the persistence of an object. There are two important interfaces for this. The IObjectTranslator-interface and the IObjectConstructor. The first interface lets you take the control over storing and activation of the object. The second interface also allows you to control the instantiation of the object.
If you register a IObjectTranslator-instance for a certain type, it will also be applied to sub-types. This doesn't apply to IObjectConstructor-instances, because those need to create the right instance and therefore cannot handle subtypes.
First you need to create a translator for your types. Let's take a look at this example. There three distinct tasks a translator has to do. The first task is to convert the not storable object into another, storable object. Another task of the translator is to take care of the activation of the object. There it need to copy the values from the stored object into a instance of the original type. The third task it to create instances of the object. There you create a instance of the original type. And for some types you maybe also read the data at this point in time.
internal class ExampleTranslator : IObjectConstructor { // This is called to store the object public Object OnStore(IObjectContainer objectContainer, Object objToStore) { NonStorableType notStorable = (NonStorableType) objToStore; return notStorable.Data; } // This is called when the object is activated public void OnActivate(IObjectContainer objectContainer, Object targetObject, Object storedObject) { NonStorableType notStorable = (NonStorableType) targetObject; notStorable.Data = (String) storedObject; } // Tell db4o which type we use to store the data public Type StoredClass() { return typeof (String); } // This method is called when a new instance is needed public Object OnInstantiate(IObjectContainer objectContainer, Object storedObject) { return new NonStorableType(""); } }
Friend Class ExampleTranslator Implements IObjectConstructor ' This is called to store the object Public Function OnStore(ByVal objectContainer As IObjectContainer, _ ByVal objToStore As Object) As Object _ Implements IObjectConstructor.OnStore Dim notStorable As NonStorableType = DirectCast(objToStore, NonStorableType) Return notStorable.Data End Function ' This is called when the object is activated Public Sub OnActivate(ByVal objectContainer As IObjectContainer, _ ByVal targetObject As Object, ByVal storedObject As Object) _ Implements IObjectConstructor.OnActivate Dim notStorable As NonStorableType = DirectCast(targetObject, NonStorableType) notStorable.Data = DirectCast(storedObject, String) End Sub ' Tell db4o which type we use to store the data Public Function StoredClass() As Type _ Implements IObjectConstructor.StoredClass Return GetType(String) End Function ' This method is called when a new instance is needed Public Function OnInstantiate(ByVal objectContainer As IObjectContainer, _ ByVal storedObject As Object) As Object _ Implements IObjectConstructor.OnInstantiate Return New NonStorableType("") End Function End Class
After that you can register the translator for you're type. If you register a IObjectTranslator-instance it will also be applied to the sub-types. However a IObjectConstructor-instance is only applied for the specific type.
IEmbeddedConfiguration configuration = Db4oEmbedded.NewConfiguration(); configuration.Common.ObjectClass(typeof(NonStorableType)).Translate(new ExampleTranslator()); IObjectContainer container = Db4oEmbedded.OpenFile(configuration, "database.db4o");
Dim configuration As IEmbeddedConfiguration = Db4oEmbedded.NewConfiguration() configuration.Common.ObjectClass(GetType(NonStorableType)).Translate(New ExampleTranslator()) Dim container As IObjectContainer = Db4oEmbedded.OpenFile(configuration, "database.db4o")
After that you can store and use the not storable objects like any other persistent objects. db4o will call the translator for each instance when required in order to store the object correctly.
container.Store(new NonStorableType("TestData"));
container.Store(New NonStorableType("TestData"))
NonStorableType data = container.Query<NonStorableType>()[0];
Dim data As NonStorableType = container.Query(Of NonStorableType)()(0)
The object translator mechanism is great for types which couldn't be stored otherwise. However there are serious limitations.