首先,protobuf-net 不打算,也不声称是 100% 的替代BinaryFormatter
. 它的功能略有不同。
你愿意做一点反思吗?基本上是支持的ImplicitFields
,但目前只能通过 获得[ProtoContract]
,不能通过 方便地完成RuntimeTypeModel
,这有点痛苦,并且在我的列表中。虽然,我应该指出,我认为隐式字段有点冒险,只有在你知道 DTO 内部不会改变的情况下才应该这样做!但是:要回答您的问题,您可以迭代您期望的类型,并将它们手动添加到模型中:
static void Main()
{
Prepare(typeof(A), typeof(B), typeof(C));
// if you really want to use IFormatter...
var formatter = RuntimeTypeModel.Default.CreateFormatter(typeof (A));
var obj = new A {Bs = new B[] {new B()}};
using (var ms = new MemoryStream())
{
formatter.Serialize(ms, obj);
ms.Position = 0;
var clone = formatter.Deserialize(ms);
}
}
static void Prepare(params Type[] types)
{
if(types != null) foreach(var type in types) Prepare(type);
}
static void Prepare(Type type)
{
if(type != null && !RuntimeTypeModel.Default.IsDefined(type))
{
Debug.WriteLine("Preparing: " + type.FullName);
// note this has no defined sort, so invent one
var props = type.GetProperties();
Array.Sort(props, (x, y) => string.Compare(
x.Name, y.Name, StringComparison.Ordinal));
var meta = RuntimeTypeModel.Default.Add(type, false);
int fieldNum = 1;
for(int i = 0 ; i < props.Length ; i++)
{
meta.Add(fieldNum++, props[i].Name);
}
}
}
注意IFormatter
这里的使用是完全没有必要的;你也可以使用RuntimeTypeModel.Default.Serialize(...)
or Serializer.Serialize<T>(...)
。
作为脚注:我建议更多地定义模型......重复。例如:
RuntimeTypeModel.Default.Add(typeof(A)).Add("Bs", "Cs");
RuntimeTypeModel.Default.Add(typeof(B)).Add("Foo");
RuntimeTypeModel.Default.Add(typeof(C)).Add("Bar", "Blap", "Blop");