是否可以在运行时指定特定抽象合同的子类型? 在经典的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; }
}
是否支持此方案?
答案 0 :(得分:0)
不支持使用GetTypes()
的方案,部分原因是如何v1处理生成/缓存 - 但是,在v2(preview available)这是可以支持的:
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; }
}
实际上,通过这种方法,您可以根据需要删除所有属性(相反地明确说明)。注意:您应该尽可能地缓存并重新使用已编译的模型 - 它是线程安全的,但每次生成它都会有点贵。