如果这是重复,我很抱歉.我在几个地方搜索了一些我可能理解的答案,包括:
我道歉但我并不真正理解答案.我正在寻找一个更快,更紧凑的二进制序列化器,ProtoBuf看起来可能是答案.我需要序列化一组所有派生自一个基类的类.它们有很多,所以在提交编辑类代码之前,我运行了一个简单的测试.此外,我不想以任何可能影响反序列化使用NET二进制序列化程序生成的旧持久文件的方式修改类.
这是基类:
[ProtoContract]
public class BaseClass
{
[ProtoMember(1)]
public string Name
{
get; set;
}
[ProtoMember(2)]
public int Age
{
get; set;
}
}
Run Code Online (Sandbox Code Playgroud)
这是派生类:
[ProtoContract]
public class SubClass1 : BaseClass
{
[ProtoMember(3)]
public string Town
{
get; set;
}
[ProtoMember(4)]
public Sex Sex
{
get; set;
}
}
Run Code Online (Sandbox Code Playgroud)
这是序列化和反序列化的代码(直接来自"入门指南"
var person = new SubClass1 { Age = 25, Name = "Fred", Town = "Denbigh", Sex = Sex.Female };
using (var file = File.Create(filename))
{
Serializer.Serialize(file, person); …Run Code Online (Sandbox Code Playgroud) 我尝试DynamicObject用BinaryFormatter,但是:序列化一个类
由于序列化一个单独的DynamicObject手段,这里是我尝试序列化的类:
[Serializable()]
class Entity
: DynamicObject, ISerializable
{
IDictionary<string, object> values = new Dictionary<string, object>();
public Entity()
{
}
protected Entity(SerializationInfo info, StreamingContext ctx)
{
string fieldName = string.Empty;
object fieldValue = null;
foreach (var field in info)
{
fieldName = field.Name;
fieldValue = field.Value;
if (string.IsNullOrWhiteSpace(fieldName))
continue;
if (fieldValue == null)
continue;
this.values.Add(fieldName, fieldValue);
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
this.values.TryGetValue(binder.Name, out result);
return …Run Code Online (Sandbox Code Playgroud) 我正在尝试用protobuf-net序列化一些对象,但不幸的是他们自由使用DateTimeOffset了protobuf-net尚未支持的对象.这导致了很多:
没有为类型定义的序列化程序:System.DateTimeOffset
我可以为未知类型定义自己的序列化例程吗?(之前曾问过同样的问题,但他的问题已得到解决.)
如果重要的话,我在.NET 4下使用最新的protobuf-net beta,v2.0.0.431.我也在使用运行时定义,因此我无法以声明方式指定如何处理某些属性.
我有2个网络应用程序,应该相互发送序列化的protobuf-net消息.我可以序列化对象并发送它们,但是,我无法弄清楚如何反序列化接收的字节.
我尝试使用它反序列化,并且失败并出现NullReferenceException.
// Where "ms" is a memorystream containing the serialized
// byte array from the network.
Messages.BaseMessage message =
ProtoBuf.Serializer.Deserialize<Messages.BaseMessage>(ms);
Run Code Online (Sandbox Code Playgroud)
我在包含消息类型ID的序列化字节之前传递一个标头,我可以在一个巨大的switch语句中使用它返回预期的sublcass Type.使用下面的块,我收到错误:System.Reflection.TargetInvocationException ---> System.NullReferenceException.
//Where "ms" is a memorystream and "messageType" is a
//Uint16.
Type t = Messages.Helper.GetMessageType(messageType);
System.Reflection.MethodInfo method =
typeof(ProtoBuf.Serializer).GetMethod("Deserialize").MakeGenericMethod(t);
message = method.Invoke(null, new object[] { ms }) as Messages.BaseMessage;
Run Code Online (Sandbox Code Playgroud)
这是我用来通过网络发送消息的功能:
internal void Send(Messages.BaseMessage message){
using (System.IO.MemoryStream ms = new System.IO.MemoryStream()){
ProtoBuf.Serializer.Serialize(ms, message);
byte[] messageTypeAndLength = new byte[4];
Buffer.BlockCopy(BitConverter.GetBytes(message.messageType), 0, messageTypeAndLength, 0, 2);
Buffer.BlockCopy(BitConverter.GetBytes((UInt16)ms.Length), 0, …Run Code Online (Sandbox Code Playgroud) 我想使用字符串序列化/反序列化对象.需要注意的是,当我序列化/反序列化到文件时,一切正常.我要做的是获取一个字符串,这样我就可以将它存储在数据库中,然后将其拉出来进行反序列化.
这是有效的代码:
MemoryStream msTest = new MemoryStream();
Serializer.Serialize(msTest, registrationBlocks);
msTest.Position = 0;
List<RVRegistrationBlock> CopiedBlocks = new List<RVRegistrationBlock>();
CopiedBlocks = Serializer.Deserialize<List<RVRegistrationBlock>>(msTest);
Run Code Online (Sandbox Code Playgroud)
"CopiedBlocks"对象与"registrationBlocks"中的列表相同,工作正常,所有序列化/反序列化.我在这里保留所有内容.
当我尝试获取字符串时,以下代码不起作用:
MemoryStream msTestString = new MemoryStream();
Serializer.Serialize(msTestString, registrationBlocks);
msTestString.Position = 0;
StreamReader srRegBlock = new StreamReader(msTestString);
byte[] bytedata64 = System.Text.Encoding.Default.GetBytes(srRegBlock.ReadToEnd());
string stringBase64 = Convert.ToBase64String(bytedata64);
byte[] byteAfter64 = Convert.FromBase64String(stringBase64);
MemoryStream afterStream = new MemoryStream(byteAfter64);
List<RVRegistrationBlock> CopiedBlocksString = new List<RVRegistrationBlock>();
CopiedBlocksString = Serializer.Deserialize<List<RVRegistrationBlock>>(afterStream);
Run Code Online (Sandbox Code Playgroud)
在反序列化的最后一行,我得到一个异常:抛出了类型'ProtoBuf.ProtoException'的异常.我无法钻进它,内部异常为null.我无法弄清楚它为什么这样做.
我肯定已经把它缩小到这样一个事实:当我得到一个字符串时它会变得混乱.我将字符串存储在nvarchar(max)的数据库中,这就是我想要字符串的原因.
任何帮助将非常感激!
在ProtoBuf-Net实现中,ProtoInclude属性意味着什么,它有什么作用?
一个例子将不胜感激.
[Serializable,
ProtoContract,
ProtoInclude(50, typeof(BeginRequest))]
abstract internal class BaseMessage
{
[ProtoMember(1)]
abstract public UInt16 messageType { get; }
}
[Serializable,
ProtoContract]
internal class BeginRequest : BaseMessage
{
[ProtoMember(1)]
public override UInt16 messageType
{
get { return 1; }
}
}
Run Code Online (Sandbox Code Playgroud)
另外,有没有办法使用protogen工具生成这种继承?
使用protobuf-net.dll版本1.0.0.280
当我反序列化DateTime(包裹在一个对象中)时,日期/时间是可以的,但DateTime.Kind属性是'未指定'
考虑这个测试用例来序列化/反序列化DateTime.
[TestMethod]
public void TestDateTimeSerialization()
{
var obj = new DateTimeWrapper {Date = DateTime.UtcNow};
obj.Date = DateTime.SpecifyKind(obj.Date, DateTimeKind.Utc);
var serialized = obj.SerializeProto();
var deserialized = serialized.DeserializeProto<DateTimeWrapper>();
Assert.AreEqual(DateTimeKind.Utc, deserialized.Date.Kind);
}
public static byte[] SerializeProto<T>(this T item) where T : class
{
using (var ms = new MemoryStream())
{
Serializer.Serialize(ms, item);
return ms.ToArray();
}
}
public static T DeserializeProto<T>(this byte[] raw) where T : class, new()
{
using (var ms = new MemoryStream(raw))
{
return Serializer.Deserialize<T>(ms); …Run Code Online (Sandbox Code Playgroud) 我看了这个答案,我的情况是我不需要保持向后兼容性,我必须有一个解决方案,无需用protobuf-net所需的属性装饰数十个类.所以我尝试使用RuntimeTypeModel.Default.InferTagFromNameDefault = true;但我可能没有正确使用它,因为Serializer.Serialize调用仍然会引发异常请求合同.这是我的快速测试,我做错了什么?
public enum CompanyTypes
{
None, Small, Big, Enterprise, Startup
}
public class BaseUser
{
public string SSN { get; set; }
}
public class User : BaseUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public DateTime BirthDate { get; set; }
public List<string> Friends { get; set; }
public Company Company { get; set; }
}
public class …Run Code Online (Sandbox Code Playgroud) 如果我有对象A和B都包含一些字段序列化字段F,并且都指向相同的可序列化对象C. protobuf-net是通过引用序列化还是按值序列化?当反序列化对象图时,protobuf-net是否会为AF和BF生成2个单独的对象?我问,因为我想知道序列化是否保留了引用相等性.
我正在尝试使用protobuf-net在C#项目中使用protobuf,并且想知道将这个组织到Visual Studio项目结构中的最佳方法是什么.
当手动使用protogen工具生成C#代码时,生活似乎很容易,但感觉不对.
我希望.proto文件被认为是主要的源代码文件,生成C#文件作为副产品,但在C#编译器参与之前.
选项似乎是:
我一直在努力与2)上面,因为它一直给我"系统找不到指定的文件",除非我使用绝对路径(我不喜欢强制项目明确定位).
还有一个约定吗?
编辑: 基于@ jon的评论,我重新尝试了预构建步骤方法,并使用Google的地址簿示例使用了这个(protogen的位置现在硬编码):
c:\bin\protobuf\protogen "-i:$(ProjectDir)AddressBook.proto"
"-o:$(ProjectDir)AddressBook.cs" -t:c:\bin\protobuf\csharp.xslt
Run Code Online (Sandbox Code Playgroud)
编辑2: 考虑到@ jon的建议,如果它们没有改变就不通过处理.proto文件来最小化构建时间,我已经敲了一个基本工具来检查我(这可能会扩展到一个完整的自定义构建工具):
using System;
using System.Diagnostics;
using System.IO;
namespace PreBuildChecker
{
public class Checker
{
static int Main(string[] args)
{
try
{
Check(args);
return 0;
}
catch (Exception e)
{
Console.WriteLine(e.Message);
return 1;
}
}
public static void Check(string[] args)
{
if (args.Length < 3)
{
throw new ArgumentException(
"Command line must be supplied with source, target and command-line [plus options]");
}
string …Run Code Online (Sandbox Code Playgroud)