May 14, 2008

Type safe / refactor friendly configuration for Db4o - Part II

In my last post I proposed to derive field names from a property accessor in order to gain type safety and compiler support when configuring some aspects of D4bo.

So, given the following class:

public class Test
{
   private int _age;
   public int Age
   {
      get { return _age; }
      set { _age = value; }
   }
}
we could use the following code:
IConfiguration cfg = Db4oFactory.NewConfiguration();
cfg.ObjectField((Test t) => t.Age).Indexed = true;
instead of:
IConfiguration cfg = Db4oFactory.NewConfiguration();
cfg.ObjectClass(typeof(Test)).ObjectField("_age").Indexed = true;
to configure a field to be indexed. The first step to use this syntax is to be able to figure out the property being accessed. To demonstrate how this can be done let's write a simple function that takes advantage of C# Expression Trees:
public string GetPropertyName<T,R>(
               Expression<Func<T,R> exp)
{
  // Get the property name here.
}

public static void Main()
{
   string s = GetPropertyName((Test t) => t.Age);
}
When compiling the above code, the C# compiler will create an expression tree representing our lambda expression ( (Test t) => t.Age) and pass it along to GetPropertyName() function.

Inside this function we can just use the Body property (which in this case represents t.Age part of our lambda expression) and cast it to MemberExpression. Now all we have to do is to consult MemberExpression.Meber.Name property:

public string GetPropertyName<T,R>(
               Expression<Func<T,R> exp)
{
    MemberExpression me = fieldExp.Body as
                             MemberExpression;
    if (me == null) return "na";

    MemberInfo m = me.Member;
    return m.DeclaringType.FullName + "." + m.Name;
}

At this point we are able to figure out the name of the property being accessed! If you take a deeper look into me.Member we will see that it is a PropertyInfo instance where you can get a lot more information about the property.

In the next post I'll dig a little bit deeper and investigate how we can select a field based on the property being accessed ;)

Thoughts?

Adriano

No comments: