首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有Bond的嵌套对象

带有Bond的嵌套对象
EN

Stack Overflow用户
提问于 2018-02-21 10:43:46
回答 1查看 556关注 0票数 0

我试图使用Microsoft来序列化嵌套对象。但邦德会抛出内部错误(如KeyNotFoundException)。

我的课:

代码语言:javascript
复制
interface IFoo
{
}

[Bond.Schema]
class Foo1 : IFoo
{
     [Bond.Id(0)]
     public string Foo1Field { get; set; }
}

[Bond.Schema]
class Bar
{
     [Bond.Id(0)]
     public IFoo SomeFooInstance { get; set; }
}

然后创建一个实例并序列化:

代码语言:javascript
复制
var src = new Bar() { SomeFooInstance = new Foo1() { Foo1Field = "Str" }};

var output = new OutputBuffer();
var writer = new CompactBinaryWriter<OutputBuffer>(output);

Serialize.To(writer, src);

var input = new InputBuffer(output.Data);
var reader = new CompactBinaryReader<InputBuffer>(input);

var dst = Deserialize<Bar>.From(reader);

但是我在Serialize.To(writer, src);上遇到了一些异常(比如Serialize.To(writer, src);)。

我也试图将[Bond.Schema]添加到IFoo中,但是Deserialize<Bar>.From(reader);失败了.

如何在不出现类似异常的情况下序列化包含某些带有邦德的Bar类的Foo类?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-02-22 02:35:44

如果您想使用具有行为差异(而不是结构差异)的接口,诀窍是为反序列化器提供一个工厂,以便它知道如何在需要时创建IFoo的具体实例。注意,实现没有[Bond.Schema]属性,因为它们都实现了IFoo模式。

代码语言:javascript
复制
namespace NS
{       
    using System;
    using Bond.IO.Unsafe;
    using Bond.Protocols;

    internal static class Program
    {
        [Bond.Schema]
        interface IFoo
        {
            [Bond.Id(10)]
            string FooField { get; set; }
        }

        [Bond.Schema]
        class Bar
        {
            [Bond.Id(20)]
            public IFoo SomeFooInstance { get; set; }
        }

        class AlwaysUppercaseFoo : IFoo
        {
            private string fooField;

            public string FooField
            {
                get
                {
                    return fooField;
                }

                set
                {
                    fooField = value.ToUpperInvariant();
                }
            }
        }

        class IdentityFoo : IFoo
        {
            public string FooField { get; set; }
        }

        public static Expression NewAlwaysUppercaseFoo(Type type, Type schemaType, params Expression[] arguments)
        {
            if (schemaType == typeof(IFoo))
            {
                return Expression.New(typeof(AlwaysUppercaseFoo));
            }

            // tell Bond we don't handle the requested type, so it should use it's default behavior
            return null;
        }

        public static Expression NewIdentityFoo(Type type, Type schemaType, params Expression[] arguments)
        {
            if (schemaType == typeof(IFoo))
            {
                return Expression.New(typeof(IdentityFoo));
            }

            // tell Bond we don't handle the requested type, so it should use it's default behavior
            return null;
        }

        public static void Main(string[] args)
        {
            var src = new Bar() { SomeFooInstance = new IdentityFoo() { FooField = "Str" } };

            var output = new OutputBuffer();
            var writer = new CompactBinaryWriter<OutputBuffer>(output);

            Bond.Serialize.To(writer, src);

            {
                var input = new InputBuffer(output.Data);
                var deserializer = new Bond.Deserializer<CompactBinaryReader<InputBuffer>>(typeof(Bar), NewAlwaysUppercaseFoo);
                var reader = new CompactBinaryReader<InputBuffer>(input);
                var dst = deserializer.Deserialize<Bar>(reader);
                Debug.Assert(dst.SomeFooInstance.FooField == "STR");
            }

            {
                var input = new InputBuffer(output.Data);
                var deserializer = new Bond.Deserializer<CompactBinaryReader<InputBuffer>>(typeof(Bar), NewIdentityFoo);
                var reader = new CompactBinaryReader<InputBuffer>(input);
                var dst = deserializer.Deserialize<Bar>(reader);
                Debug.Assert(dst.SomeFooInstance.FooField == "Str");
            }
        }
    }
}

如果需要行为和结构上的差异,那么需要将其与多态bonded<IFoo>字段配对,以便可以延迟反序列化,直到有足够的类型信息来选择适当的实现为止。(多态性是显式的,并选择在Bond中加入。)

我会给出一个例子,但是在2018-02-21上写这个答案时,我发现了一个[Bond.Schema]:接口中的字段被省略了。

目前,解决办法是对类使用继承和使用虚拟属性。例如:

代码语言:javascript
复制
namespace NS
{
    using System;
    using Bond.IO.Unsafe;
    using Bond.Protocols;

    internal static class Program
    {
        enum FooKind
        {
            Unknown = 0,
            AlwaysUppercase = 1,
            Identity = 2,
        }

        // intentionally a class to work around https://github.com/Microsoft/bond/issues/801 but simulate an interface somewhat
        [Bond.Schema]
        class IFoo
        {
            [Bond.Id(0)]
            public virtual string FooField { get; set; }
        }

        [Bond.Schema]
        class Bar
        {
            [Bond.Id(0)]
            public Bond.IBonded<IFoo> SomeFooInstance { get; set; }

            [Bond.Id(1)]
            public FooKind Kind { get; set; }
        }

        [Bond.Schema]
        class AlwaysUppercaseFoo : IFoo
        {
            private string fooField;

            public override string FooField
            {
                get
                {
                    return fooField;
                }

                set
                {
                    fooField = value.ToUpperInvariant();
                }
            }

            [Bond.Id(0)]
            public string JustAlwaysUppercaseFooField { get; set; }
        }

        [Bond.Schema]
        class IdentityFoo : IFoo
        {
            [Bond.Id(42)]
            public string JustIdentityFooField { get; set; }
        }

        static void RoundTripAndPrint(Bar src)
        {
            var output = new OutputBuffer();
            var writer = new CompactBinaryWriter<OutputBuffer>(output);

            Bond.Serialize.To(writer, src);

            var input = new InputBuffer(output.Data);
            var reader = new CompactBinaryReader<InputBuffer>(input);
            var dst = Bond.Deserialize<Bar>.From(reader);

            switch (dst.Kind)
            {
                case FooKind.Identity:
                    {
                        var fooId = dst.SomeFooInstance.Deserialize<IdentityFoo>();
                        Console.WriteLine($"IdFoo: \"{fooId.FooField}\", \"{fooId.JustIdentityFooField}\"");
                    }
                    break;

                case FooKind.AlwaysUppercase:
                    {
                        var fooUc = dst.SomeFooInstance.Deserialize<AlwaysUppercaseFoo>();
                        Console.WriteLine($"UcFoo: \"{fooUc.FooField}\", \"{fooUc.JustAlwaysUppercaseFooField}\"");
                    }
                    break;

                default:
                    Console.WriteLine($"Unknown Kind: {dst.Kind}");
                    break;
            }
        }

        public static void Main(string[] args)
        {
            var o = new OutputBuffer();
            var w = new CompactBinaryWriter<OutputBuffer>(o);
            Bond.Serialize.To(w, new IdentityFoo() { FooField = "Str", JustIdentityFooField = "id" });

            var src_id = new Bar()
            {
                SomeFooInstance = new Bond.Bonded<IdentityFoo>(new IdentityFoo() { FooField = "Str", JustIdentityFooField = "id" }),
                Kind = FooKind.Identity
            };

            var src_uc = new Bar()
            {
                SomeFooInstance = new Bond.Bonded<AlwaysUppercaseFoo>(new AlwaysUppercaseFoo() { FooField = "Str", JustAlwaysUppercaseFooField = "I LIKE TO YELL!" }),
                Kind = FooKind.AlwaysUppercase
            };

            RoundTripAndPrint(src_id);
            RoundTripAndPrint(src_uc);
        }
    }
}

这些指纹:

IdFoo:"Str","id“UcFoo:"STR",”我喜欢大叫!“

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48903908

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档