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.
01/* Copyright (C) 2005 db4objects Inc. http://www.db4o.com */ 02
using System; 03
using Sharpen.Lang ; 04
05
namespace 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
}
01' Copyright (C) 2004 - 2006 db4objects Inc. http://www.db4o.com 02
03
Imports System 04
Imports Db4objects.Db4o.Reflect 05
Imports Db4objects.Db4o.Reflect.Net 06
07
Namespace 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 89
End 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:
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
}
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.