0

几天以来,我一直在尝试使用 db4o,但遇到了问题。

想象一下这个类只是为了测试:

    class Test
{
  public string TestString
  public int Number;
  public Bitmap Bm;
  public Test2 T2;

}

我正在保存整个类和所有子对象。但是当我加载它时,我不希望 Bm 被加载(只是让它为空)。我怎么能把它排除在外?我需要保存它,因为在某些情况下,我需要加载它。这是一个表演的事情,因为图片真的很大。

4

1 回答 1

0

好吧,最简单的解决方案(恕我直言)是将 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);
        }
    }
}

你也可以玩激活深度

希望这有帮助。

于 2013-08-09T20:21:48.407 回答