protobuf-net 中的继承在运行时解析

发布于 2024-11-01 04:50:51 字数 795 浏览 3 评论 0原文

是否可以在运行时指定特定抽象合约的子类型? 在经典的 WCF/DataContract 中,我们有 KnownTypeAttribute 及其构造函数,该构造函数接受表示要调用以获取一组 Type:s 的静态函数名称的字符串。

[DataContract]
[KnownType("GetTypes")]
public abstract class AbstractContract
{
    [DataMember] public int Prop1 { get; set; }
    [DataMember] public string Prop2 { get; set; }

    static IEnumerable<Type> GetTypes()
    {
        var list = new List<Type>();
        list.Add(typeof(ConcreteContract1));
        list.Add(typeof(ConcreteContract2));

        return list;
    }
}

[DataContract]
public class ConcreteContract1 : AbstractContract
{
    [DataMember] public int Prop3 { get; set; }
}

[DataContract]
public class ConcreteContract2 : AbstractContract
{
    [DataMember] public bool Prop3 { get; set; }
}

支持这种场景吗?

Is it possible to specify at runtime the sub-types of a specific abstract contract?
In the classic WCF/DataContract we have the KnownTypeAttribute and its constructor accepting a string representing the name of static function to invoke to get a set of Type:s.

[DataContract]
[KnownType("GetTypes")]
public abstract class AbstractContract
{
    [DataMember] public int Prop1 { get; set; }
    [DataMember] public string Prop2 { get; set; }

    static IEnumerable<Type> GetTypes()
    {
        var list = new List<Type>();
        list.Add(typeof(ConcreteContract1));
        list.Add(typeof(ConcreteContract2));

        return list;
    }
}

[DataContract]
public class ConcreteContract1 : AbstractContract
{
    [DataMember] public int Prop3 { get; set; }
}

[DataContract]
public class ConcreteContract2 : AbstractContract
{
    [DataMember] public bool Prop3 { get; set; }
}

Is this scenario supported?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迟到的我 2024-11-08 04:50:51

不支持使用 GetTypes() 的场景,部分原因是 v1 如何处理生成/缓存 -但是,在 v2 中 (预览可用)这是支持的:

using System;
using System.Runtime.Serialization;
using ProtoBuf.Meta;

class Program
{
    static void Main()
    {
        var model = TypeModel.Create();
        var abst = model.Add(typeof(AbstractContract), true);
        // define inheritance here...
        abst.AddSubType(10, typeof(ConcreteContract1));
        abst.AddSubType(11, typeof(ConcreteContract2));
        model.CompileInPlace();

        AbstractContract foo = new ConcreteContract1 { Prop1 = 123, Prop2 = "abc", Prop3 = 456 };
        AbstractContract bar = (AbstractContract)model.DeepClone(foo);

        Console.WriteLine(bar.Prop1);
        Console.WriteLine(bar.Prop2);
        Console.WriteLine(((ConcreteContract1)bar).Prop3);
    }
}



[DataContract]
public abstract class AbstractContract
{
    [DataMember(Order=1)]
    public int Prop1 { get; set; }
    [DataMember(Order=2)]
    public string Prop2 { get; set; }
}

[DataContract]
public class ConcreteContract1 : AbstractContract
{
    [DataMember(Order=1)]
    public int Prop3 { get; set; }
}

[DataContract]
public class ConcreteContract2 : AbstractContract
{
    [DataMember(Order=1)]
    public bool Prop3 { get; set; }
}

实际上,通过这种方法,您可以删除所有属性,如果您想要(而是明确地告诉它)。注意:您应该尽可能缓存并重用编译后的模型 - 它是线程安全的,但每次生成它会更昂贵一些。

The scenario with GetTypes() isn't supported, partly due to how to v1 handles the generation/caching -however, in v2 (preview available) this is supoortable:

using System;
using System.Runtime.Serialization;
using ProtoBuf.Meta;

class Program
{
    static void Main()
    {
        var model = TypeModel.Create();
        var abst = model.Add(typeof(AbstractContract), true);
        // define inheritance here...
        abst.AddSubType(10, typeof(ConcreteContract1));
        abst.AddSubType(11, typeof(ConcreteContract2));
        model.CompileInPlace();

        AbstractContract foo = new ConcreteContract1 { Prop1 = 123, Prop2 = "abc", Prop3 = 456 };
        AbstractContract bar = (AbstractContract)model.DeepClone(foo);

        Console.WriteLine(bar.Prop1);
        Console.WriteLine(bar.Prop2);
        Console.WriteLine(((ConcreteContract1)bar).Prop3);
    }
}



[DataContract]
public abstract class AbstractContract
{
    [DataMember(Order=1)]
    public int Prop1 { get; set; }
    [DataMember(Order=2)]
    public string Prop2 { get; set; }
}

[DataContract]
public class ConcreteContract1 : AbstractContract
{
    [DataMember(Order=1)]
    public int Prop3 { get; set; }
}

[DataContract]
public class ConcreteContract2 : AbstractContract
{
    [DataMember(Order=1)]
    public bool Prop3 { get; set; }
}

Actually, with this approach you can take away all the attributes if you want (telling it explicitly instead). Note: you should cache and re-use the compiled model as far as possible - it is thread-safe, but generating it each time will be a bit more expensive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文