好吧,最简单的解决方案(恕我直言)是将 BitMap 类包装在另一个类中并使用 db4o 的透明激活功能:
using System;
using System.IO;
using System.Linq;
using Db4objects.Db4o;
using Db4objects.Db4o.Activation;
using Db4objects.Db4o.TA;
namespace ActivationDepth
{
class Program
{
static void Main(string[] args)
{
var dbFilePath = Path.GetTempFileName();
using (var db = Db4oEmbedded.OpenFile(dbFilePath))
{
db.Store(new C1 { Name = "c1", Huge = new MyHugeClass("I am really huge....")});
}
var config = Db4oEmbedded.NewConfiguration();
config.Common.Add(new TransparentActivationSupport());
config.Common.ActivationDepth = 0;
using (var db = Db4oEmbedded.OpenFile(config, dbFilePath))
{
var item = db.Query<C1>().ElementAt(0);
Console.WriteLine("{0}", db.Ext().IsActive(item));
Console.WriteLine("[Huge] {0} : {1}", db.Ext().IsActive(item.huge), item.huge);
Console.WriteLine("[Huge] {0} : {1}", db.Ext().IsActive(item.Huge), item.Huge);
}
}
}
class C1 : IActivatable
{
public string Name
{
get
{
Activate(ActivationPurpose.Read);
return name;
}
set
{
Activate(ActivationPurpose.Write);
name = value;
}
}
public MyHugeClass Huge
{
get
{
Activate(ActivationPurpose.Read);
return huge;
}
set
{
Activate(ActivationPurpose.Write);
huge = value;
}
}
public override string ToString()
{
Activate(ActivationPurpose.Read);
return string.Format("[{0}] {1}", GetType().Name, name);
}
public void Bind(IActivator activator)
{
if (this.activator != null && activator != null)
{
throw new Exception("activation already set");
}
this.activator = activator;
}
public void Activate(ActivationPurpose purpose)
{
if (activator != null)
{
activator.Activate(purpose);
}
}
public MyHugeClass huge;
private string name;
[NonSerialized]
private IActivator activator;
}
class MyHugeClass : IActivatable
{
public string Name
{
get
{
Activate(ActivationPurpose.Read);
return name;
}
set
{
Activate(ActivationPurpose.Write);
name = value;
}
}
public MyHugeClass(string name)
{
this.name = name;
}
public override string ToString()
{
Activate(ActivationPurpose.Read);
return string.Format("[{0}] {1}", GetType().Name, name);
}
public void Bind(IActivator activator)
{
if (this.activator != null && activator != null)
{
throw new Exception("activation already set");
}
this.activator = activator;
}
public void Activate(ActivationPurpose purpose)
{
if (activator != null)
{
activator.Activate(purpose);
}
}
private string name;
[NonSerialized]
private IActivator activator;
}
}
请注意,即使我手动实现了 IActivatable 接口,我也不建议这样做;您可以使用 db4otool 自动为您实现它。
另一种可能的解决方案是控制您的类型的激活(当一个对象在 db4o 中未激活时,它的引用是有效的,但它的所有字段都不会被初始化,不占用任何空间)。
例如,您可以执行以下操作:
using System;
using System.IO;
using System.Linq;
using Db4objects.Db4o;
using Db4objects.Db4o.Events;
namespace ActivationDepth
{
class Program
{
static void Main(string[] args)
{
var dbFilePath = Path.GetTempFileName();
using (var db = Db4oEmbedded.OpenFile(dbFilePath))
{
db.Store(new C1 { name = "c1", c2 = new C2("c2"), huge = new MyHugeClass("I am really huge....")});
}
var config = Db4oEmbedded.NewConfiguration();
using (var db = Db4oEmbedded.OpenFile(config, dbFilePath))
{
var activate = false;
var fac = EventRegistryFactory.ForObjectContainer(db);
fac.Activating += (sender, eventArgs) =>
{
if (!activate && eventArgs.Object.GetType() == typeof(MyHugeClass))
{
Console.WriteLine("[{0}] Ignoring activation.", eventArgs.Object);
eventArgs.Cancel();
}
else
{
Console.WriteLine("[{0}] Activation will proceed.", eventArgs.Object);
}
};
var item = db.Query<C1>().ElementAt(0);
Console.WriteLine("[IsActive] {0}", db.Ext().IsActive(item.huge));
activate = true;
db.Activate(item.huge, 3);
Console.WriteLine("[IsActive] {0}", db.Ext().IsActive(item.huge));
}
}
}
class C1
{
public string name;
public C2 c2;
public MyHugeClass huge;
public override string ToString()
{
return string.Format("[{0}] {1}", GetType().Name, name);
}
}
class C2
{
public string name;
public C2(string name)
{
this.name = name;
}
public override string ToString()
{
return string.Format("[{0}] {1}", GetType().Name, name);
}
}
class MyHugeClass
{
public string text;
public MyHugeClass(string text)
{
this.text = text;
}
public override string ToString()
{
return string.Format("[{0}] {1}", GetType().Name, text);
}
}
}
你也可以玩激活深度。
希望这有帮助。