
课程咨询: 400-996-5531 / 投诉建议: 400-111-8989
认真做教育 专心促就业
ASP.NET Core 使用protobuf在一些性能要求很高的应用中,使用protocol buffer序列化,优于Json。而且protocol buffer向后兼容的能力比较好。
由于# core 采用了全新的MiddleWare方式,因此使用protobuf序列化,只需要使用Protobuf-net修饰需要序列化的对象,并在MVC初始化的时候增加相应的Formatter就可以了。
MVC Controller 的Action返回对象时,MVC回根据用户的Request Header里面的MIME选择对应的Formater来序列化返回对象( Serialize returned object)。
MVC具有默认的Json Formater,这个可以不用管。
这里有一个直接可以运行的例子,具有Server和Client代码
但是,这里面有一个很严重的问题。 看下面的例子。例如我们需要序列化的对象时ApparatusType,服务端的定义(使用了EntityFramework)是这样的:
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using ProtoBuf;
namespace Hammergo.Data
{
[ProtoContract]
public partial class ApparatusType
{
public ApparatusType()
{
this.Apps = new List();
}
[ProtoMember(1)]
public System.Guid Id { get; set; }
[ProtoMember(2)]
[MaxLength(20)]
public string TypeName { get; set; }
[ProtoIgnore]
public virtual ICollection Apps { get; set; }
}
}
属于ProtoBuf 的三个修饰为
[ProtoContract]
[ProtoMember(1)]
[ProtoMember(2)]
其他的不用管,在客户端定义是这样的
using System;
using System.Collections.Generic;
using ProtoBuf;
namespace Hammergo.Poco
{
[ProtoContract]
public class ApparatusType
{
[ProtoMember(1)]
public virtual System.Guid Id { get; set; }
[ProtoMember(2)]
public virtual string TypeName { get; set; }
}
}
这里使用了Virtual关键字,是为了生成POCO的代理类,以跟踪状态,没有这个要求可以不使用。
如果ASP.NET 的action返回List,在客户端使用
var result =
response.Content.ReadAsAsync>(new[] { new ProtoBufFormatter() }).Result;
就会抛出异常,ReadAsAsync ProtoBuf Formatter No MediaTypeFormatter is available to read
大意是没有 相应的MediaTypeFormatter来供ReadAsAsync来使用,
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Net.Http.Headers;
using System.Reflection;
using System.Threading.Tasks;
using ProtoBuf;
using ProtoBuf.Meta;
namespace WebApiContrib.Formatting
{
public class ProtoBufFormatter : MediaTypeFormatter
{
private static readonly MediaTypeHeaderValue mediaType = new MediaTypeHeaderValue("application/x-protobuf");
private static Lazy model = new Lazy(CreateTypeModel);
public static RuntimeTypeModel Model
{
get { return model.Value; }
}
public ProtoBufFormatter()
{
SupportedMediaTypes.Add(mediaType);
}
public static MediaTypeHeaderValue DefaultMediaType
{
get { return mediaType; }
}
public override bool CanReadType(Type type)
{
return CanReadTypeCore(type);
}
public override bool CanWriteType(Type type)
{
return CanReadTypeCore(type);
}
public override Task