Creating your own reflector

By default db4o uses JdkReflector(Java) or NetReflector (.NET) as a GenericReflector delegate.

However, the programmer can instruct db4o to use a specially designed reflection implementation:

c#: Db4oFactory.Configure().ReflectWith(reflector)

VB: Db4oFactory.Configure().ReflectWith(reflector)

where reflector is one of the available reflectors or your own reflector implementation.

At present db4o comes with SelfReflector, which was designed for environments, which do not have built-in support for reflections (J2ME for example). In this implementation all the classes' information is stored in special registry. User classes should implement self_get and self_set methods to be registered individually and become "known" to SelfReflector.

Specific reflectors can be written for special usecases.

Let's look how to create a reflector. Remember that db4o relies on reflector to read the database, so errors in reflector may prevent your database from opening.

To keep things simple we will write a LoggingReflector, its only difference from standard reflector is that information about loaded classes is outputted to console. All reflectors used by db4o should implement com.db4o.reflect.Reflector interface.

LoggingReflector.cs
01/* Copyright (C) 2005 db4objects Inc. http://www.db4o.com */ 02using System; 03using Sharpen.Lang ; 04 05namespace Db4objects.Db4odoc.Reflections 06{ 07 public class LoggingReflector : Db4objects.Db4o.Reflect.IReflector 08 { 09 private LoggingArray _arrayHandler; 10 private Db4objects.Db4o.Reflect.IReflector _parent; 11 12 public LoggingReflector() 13 { 14 } 15 16 public virtual Db4objects.Db4o.Reflect.IReflectArray Array() 17 { 18 if (_arrayHandler == null) 19 { 20 _arrayHandler = new LoggingArray(_parent); 21 } 22 return _arrayHandler; 23 } 24 25 public virtual bool ConstructorCallsSupported() 26 { 27 return true; 28 } 29 30 public virtual Db4objects.Db4o.Reflect.IReflectClass ForName(string className) 31 { 32 System.Type clazz = null; 33 try 34 { 35 clazz = TypeReference.FromString(className).Resolve(); 36 } 37 catch (System.Exception) 38 { 39 } 40 Db4objects.Db4o.Reflect.IReflectClass rc = clazz == null 41 ? null 42 : new Db4objects.Db4o.Reflect.Net.NetClass(_parent, clazz); 43 Console.WriteLine("ForName: " + clazz + " -> " + (rc == null ? "" : rc.GetName())); 44 return rc; 45 } 46 47 public virtual Db4objects.Db4o.Reflect.IReflectClass ForObject(object a_object) 48 { 49 if (a_object == null) 50 { 51 return null; 52 } 53 Db4objects.Db4o .Reflect .IReflectClass rc = _parent.ForClass(a_object.GetType()); 54 Console.WriteLine("ForObject:" + a_object+" -> "+(rc== null ? "" : rc.GetName())); 55 return rc; 56 } 57 58 public virtual bool IsCollection(Db4objects.Db4o.Reflect.IReflectClass candidate) 59 { 60 bool result = false; 61 if (candidate.IsArray()) 62 { 63 result = false; 64 } 65 if (typeof(System.Collections.ICollection).IsAssignableFrom( 66 ((Db4objects.Db4o.Reflect.Net.NetClass)candidate).GetNetType())) 67 { 68 result = true; 69 } 70 Console.WriteLine("Type " + candidate.GetName () + " is Collection " + result); 71 return result; 72 } 73 74 public virtual object DeepClone(object context) 75 { 76 return new LoggingReflector(); 77 } 78 79 public Db4objects.Db4o.Reflect.IReflectClass ForClass(Type clazz) 80 { 81 Db4objects.Db4o.Reflect.IReflectClass rc = new Db4objects.Db4o.Reflect.Net.NetClass(_parent, clazz); 82 Console.WriteLine("ForClass: " + clazz + " -> " + (rc == null ? "" : rc.GetName())); 83 return rc; 84 } 85 86 public void SetParent(Db4objects.Db4o.Reflect.IReflector reflector) 87 { 88 _parent = reflector; 89 } 90 91 } 92}

LoggingReflector.vb
01' Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com 02 03Imports System 04Imports Db4objects.Db4o.Reflect 05Imports Db4objects.Db4o.Reflect.Net 06 07Namespace Db4objects.Db4odoc.Reflections 08 Public Class LoggingReflector 09 Implements IReflector 10 Private _arrayHandler As LoggingArray 11 Private _parent As IReflector 12 13 Public Sub New() 14 End Sub 15 16 Public Overridable Function Array() As IReflectArray Implements IReflector.Array 17 If _arrayHandler Is Nothing Then 18 _arrayHandler = New LoggingArray(_parent) 19 End If 20 Return _arrayHandler 21 End Function 22 23 Public Overridable Function ConstructorCallsSupported() As Boolean Implements IReflector.ConstructorCallsSupported 24 Return True 25 End Function 26 27 Public Overridable Function ForClass(ByVal clazz As System.Type) As IReflectClass Implements IReflector.ForClass 28 Dim rc As IReflectClass = New NetClass(_parent, clazz) 29 If rc Is Nothing Then 30 Console.WriteLine("ForClass: " + clazz.FullName + " -> ... ") 31 Else 32 Console.WriteLine("ForClass: " + clazz.FullName + " -> " + (rc.GetName())) 33 End If 34 Return rc 35 End Function 36 37 Public Overridable Function ForName(ByVal className As String) As IReflectClass Implements IReflector.ForName 38 Dim clazz As System.Type = Nothing 39 Try 40 clazz = Sharpen.Lang.TypeReference.FromString(className).Resolve() 41 42 Catch e As System.TypeLoadException 43 Return Nothing 44 End Try 45 46 Dim rc As IReflectClass = ForClass(clazz) 47 If rc Is Nothing Then 48 Console.WriteLine("ForName: " + clazz.FullName + " -> ... ") 49 Else 50 Console.WriteLine("ForName: " + clazz.FullName + " -> " + (rc.GetName())) 51 End If 52 Return rc 53 54 End Function 55 56 Public Overridable Function ForObject(ByVal a_object As Object) As IReflectClass Implements IReflector.ForObject 57 If a_object Is Nothing Then 58 Return Nothing 59 End If 60 Dim rc As IReflectClass = _parent.ForClass(a_object.GetType()) 61 If rc Is Nothing Then 62 Console.WriteLine("ForObject: " + a_object.ToString + " -> ... ") 63 Else 64 Console.WriteLine("ForObject: " + a_object.ToString + " -> " + (rc.GetName())) 65 End If 66 Return rc 67 End Function 68 69 Public Overridable Function IsCollection(ByVal candidate As IReflectClass) As Boolean Implements IReflector.IsCollection 70 Dim result As Boolean = False 71 If (candidate.IsArray()) Then 72 result = False 73 End If 74 If (GetType(System.Collections.ICollection).IsAssignableFrom((CType(candidate, NetClass).GetNetType()))) Then 75 result = True 76 End If 77 Console.WriteLine("Type " + candidate.GetName() + " isCollection: " + result.ToString()) 78 Return result 79 End Function 80 81 Public Overridable Sub SetParent(ByVal reflector As IReflector) Implements IReflector.SetParent 82 _parent = reflector 83 End Sub 84 85 Public Overridable Function DeepClone(ByVal context As Object) As Object Implements IReflector.DeepClone 86 Return New LoggingReflector() 87 End Function 88 End Class 89End Namespace

It is easy to see that this reflector provides the same functionality as JdkReflector or NetReflector extended by console output. The following simple test will show how it works:

ReflectorExample.cs: TestReflector
01public static void TestReflector() 02 { 03 LoggingReflector logger = new LoggingReflector(); 04 Db4oFactory.Configure().ReflectWith(logger); 05 IObjectContainer db = Db4oFactory.OpenFile(YapFileName); 06 try 07 { 08 Car car = new Car("BMW"); 09 IReflectClass rc = db.Ext().Reflector().ForObject(car); 10 Console.WriteLine("Reflected class: " + rc); 11 } 12 finally 13 { 14 db.Close(); 15 } 16 }

ReflectorExample.vb: TestReflector
01Public Shared Sub TestReflector() 02 Dim logger As LoggingReflector = New LoggingReflector() 03 Db4oFactory.Configure().ReflectWith(logger) 04 Dim db As IObjectContainer = Db4oFactory.OpenFile(YapFileName) 05 Try 06 Dim car As Car = New Car("BMW") 07 Dim rc As IReflectClass 08 rc = db.Ext().Reflector().ForObject(car) 09 Console.WriteLine("Reflected class: " + rc.GetName()) 10 Finally 11 db.Close() 12 End Try 13 End Sub

The output can help you to track all the loaded classes.

Reflection is a powerful tool, which plays a fundamental role in db4o. Understanding reflection will help you to understand the whole db4o functionality in detail.