Question

I am wondering: if I load an object from a db4o database, will field initializers always be called?

An example could be a transient field syncRoot, used for object locking, because of thread-safety:

public class Test
{
    [Transient]
    private object syncRoot = new object();

    [Transient]
    private object syncRoot2;

    public Test()
    {
        this.syncRoot2 = new object();
    }
}

The db4o query is like:

Test mytestObject = (from Test test in session
                     select test).First(); 

I can't use syncRoot2 because during the db4o query, the object constructors are not called, so the value will be null. But what about syncRoot? Is it safe to use field initializers on db4o model objects?

Was it helpful?

Solution

It depends :)

By default no, since db4o will try to avoid calling the ctor and field initializers are executed within the ctor) (at least using C# compiler shipped with VS 2010).

For example, given the following class definition:

public class Item
{
   public object o = new object();
}

C# compiler will emit IL (for the constructor) similar to:

.class public auto ansi beforefieldinit Item extends [mscorlib]System.Object
{
   .field public object o
   .field public notserialized int32 i

   .method public hidebysig specialname rtspecialname 
                  instance void .ctor () cil managed 
   {
        .maxstack 8

        ldarg.0
        newobj instance void [mscorlib]System.Object::.ctor()  // field initializer
        stfld object Item::o // field initializer
        ldarg.0
        call instance void [mscorlib]System.Object::.ctor()
        ret
   }
}

Basically you have two options here:

  1. Enable constructor invocations
  2. Use Activated event to initialize the transient fields.

Hope this helps

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top