You are here: Advanced Features > Type Handling > Translators

Translators

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.

Creating a Translator

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("");
    }
}
ExampleTranslator.cs: An example translator
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
ExampleTranslator.vb: An example translator

Registering a Translator

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");
ExampleTranslator.cs: Register type translator for the NonStorableType-class
Dim configuration As IEmbeddedConfiguration = Db4oEmbedded.NewConfiguration()
configuration.Common.ObjectClass(GetType(NonStorableType)).Translate(New ExampleTranslator())
Dim container As IObjectContainer = Db4oEmbedded.OpenFile(configuration, "database.db4o")
ExampleTranslator.vb: Register type translator for the NonStorableType-class

Using The Translator

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"));
ExampleTranslator.cs: Store the non storable type
container.Store(New NonStorableType("TestData"))
ExampleTranslator.vb: Store the non storable type
NonStorableType data = container.Query<NonStorableType>()[0];
ExampleTranslator.cs: Load the non storable type
Dim data As NonStorableType = container.Query(Of NonStorableType)()(0)
ExampleTranslator.vb: Load the non storable type

Limitations

The object translator mechanism is great for types which couldn't be stored otherwise. However there are serious limitations.