Наследование разрешается во время выполнения в protobuf-Net - PullRequest
1 голос
/ 13 апреля 2011

Можно ли указать во время выполнения подтипы конкретного абстрактного контракта?В классическом WCF / DataContract у нас есть KnownTypeAttribute и его конструктор, принимающий строку, представляющую имя статической функции, вызываемой для получения набора типов: 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; }
}

Поддерживается ли этот сценарий?

1 Ответ

0 голосов
/ 13 апреля 2011

Сценарий с 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; }
}

На самом деле, при таком подходе вы можете убрать все атрибуты, если хотите (вместо этого сказать явно).Примечание: вы должны кэшировать и повторно использовать скомпилированную модель, насколько это возможно - она ​​поточнобезопасна, но генерировать ее каждый раз будет немного дороже.

...