我可以将net.tcp绑定用于protobuf-net WCF吗?
我可以使用ClientBase还是必须使用ProtoClient?
我已经开始使用protobuf-net lib在我正在维护的一些程序之间进行通信.我也能够将C#中的消息解码为Ruby.我的ruby ProtoBuf lib使用.proto文件生成ruby代码.为了不得不在尽可能少的地方进行更改,我希望protobuf-net使用相同的.proto文件.虽然看起来protobuf-net文件夹有一个名为ProtoBufGenerator和protobuf exe的Dll,但我无法找到任何关于我是否可以通过这种方式使protobuf-net工作的指令.
这可能吗?
请观察以下简单程序(基于protobuf-net项目v1 wiki的示例):
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using ProtoBuf;
namespace HelloProtoBuf
{
[ProtoContract]
class Person
{
[ProtoMember(1)]
public int Id { get; set; }
[ProtoMember(2)]
public string Name { get; set; }
[ProtoMember(3)]
public Address Address { get; set; }
}
[ProtoContract]
class Address
{
[ProtoMember(1)]
public string Line1 { get; set; }
[ProtoMember(2)]
public string Line2 { get; set; }
}
class Program
{
static void Main(string[] args)
{
var person = new Person
{
Id = 12345, …Run Code Online (Sandbox Code Playgroud) 我正在使用协议缓冲区序列化序列化大型数据集.当我的数据集包含400000个大小约为1 GB的自定义对象时,序列化将在3~4秒内返回.但是当我的数据集包含大约1.2 GB的450000个组合大小的对象时,序列化调用永远不会返回并且CPU会不断消耗.
我正在使用Protocol Buffers的.NET端口.
我得到一个ProtoException("可能的递归检测到(偏移:4级):o EOW")序列化树结构时如下:
var tree = new PrefixTree();
tree.Add("racket".ToCharArray());
tree.Add("rambo".ToCharArray());
using (var stream = File.Open("test.prefix", FileMode.Create))
{
Serializer.Serialize(stream, tree);
}
Run Code Online (Sandbox Code Playgroud)
树实现:
[ProtoContract]
public class PrefixTree
{
public PrefixTree()
{
_nodes = new Dictionary<char, PrefixTree>();
}
public PrefixTree(char[] chars, PrefixTree parent)
{
if (chars == null) throw new ArgumentNullException("chars");
if (parent == null) throw new ArgumentNullException("parent");
if (chars.Length == 0) throw new ArgumentException();
_parent = parent;
_nodes = new Dictionary<char, PrefixTree>();
_value = chars[0];
var overflow = chars.SubSet(1);
if (!overflow.Any()) …Run Code Online (Sandbox Code Playgroud) protobuf-net实现的一个限制是它同步调用底层流.通过不提供异步API,例如BeginSerialize/EndSerialize或TPL等价物,我们被迫绑定一个等待同步流I/O的线程.
有没有计划在protobuf-net中提供异步方法,或者有任何创造性的方法来解决这个问题?
有没有办法处理一个事件或回调刚刚被Protobuf反序列化的对象,而不必明确地从反序列化对象中调用该方法?
例如,假设我有以下课程:
[ProtoContract]
public class Customer
{
[ProtoMember(1)]
public string FirstName { get; set; }
[ProtoMember(2)]
public string MiddleName { get; set; }
[ProtoMember(3)]
public string LastName { get; set; }
[ProtoMember(4)]
public Dictionary<int, string> Addresses { get; set; }
public Customer()
{
//Subscibe to a Protobuf deserialization complete event?
}
public void ValidateAddresses()
{
//Some routine to validate addresses
}
}
Run Code Online (Sandbox Code Playgroud)
是否有办法调用"ValidateAddresses"而不必从反序列化的代码块中的反序列化对象中显式调用它?在构造函数中调用它是没有价值的,因为Protobuf还没有应用序列化的值,所以有一种方法可以知道它何时完成应用值.我希望有一种方法可以实现这一点,以消除在对象被使用的任何地方重构后反序列化调用的需要.
我有一些想法,但我想我会先发布这个问题,然后再向前证明这些问题,以防万一有人有一个我还没有看到的更好的(这很可能).提前致谢.
主要目标是动态填充Dictionary对象并使用Protobuf-net对其进行序列化,并将其通过WCF服务发送到客户端.
@marc你可以告诉我一个代码示例,当我尝试使用Protobuf-net进行序列化时,如何解决错误"不支持嵌套或锯齿状列表和数组".
[Serializable]
[ProtoContract]
public class DynamicWrapper
{
[ProtoMember(1)]
public List<Dictionary<string, string>> Items { get; set; }
public DynamicWrapper()
{
Items = new List<Dictionary<string, string>>();
}
}
public class Service1 : IService1
{
public byte[] GetData(string sVisibleColumnList)
{
DynamicWrapper dw = new DynamicWrapper();
Dictionary<string, string> d = new Dictionary<string, string>();
d.Add("CUSIP", "123456");
dw.Items.Add(d);
d = new Dictionary<string, string>();
d.Add("ISIN", "456789");
dw.Items.Add(d);
var ms = new MemoryStream();
var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
model.Serialize(ms, dw);
Serializer.Serialize <DynamicWrapper>(ms, dw);
return ms.GetBuffer();
} …Run Code Online (Sandbox Code Playgroud) 首先,这不是IEnumerable <T>的副本作为WCF方法的返回类型,我想我明白WCF架构只允许传输可以填充到消息中的具体类型.
其次,我们的设置不是一般服务,而是通过C#+ WCF + NetTcpBinding + Protobuf(仅)连接一组专有应用程序,因此我们可能有更多空间来处理某些需要更具约束力中性的技巧.
第三,提出不同的RPC或消息框架既不是我的地方,也不是这个问题.
出于这个问题的目的,"IEnumerable语义"是:
List或相似.foreach并完成它.在本地程序集中,C#接口看起来像这样:
interface IStuffProvider {
IEnumerable<Stuff> GetItems(); // may open large file or access database
}
Run Code Online (Sandbox Code Playgroud)
您无法将其直接映射到WCF服务.可能达到相同效果的东西可能如下所示:
[ServiceContract(SessionMode = SessionMode.Required)]
interface IStuffService {
[OperationContract]
void Reset(); // may open large file or access database
[OperationContract]
List<Stuff> GetNext(); // return next batch of items (empty list if no more available)
} …Run Code Online (Sandbox Code Playgroud) 我有一个小单元测试来测试循环依赖.
我的目标如下:
[ProtoContract]
public class Node
{
[ProtoMember(1)]
public String Name { get; set; }
[ProtoMember(2,AsReference = true)]
public List<Node> Childs { get; set; }
public Node()
{
Childs = new List<Node>();
}
}
Run Code Online (Sandbox Code Playgroud)
以下服务:
[ServiceContract]
public interface INodeService : IService
{
[OperationContract]
Task<Node> GetCyclicNodes();
}
public class NodeService : Service, INodeService
{
public async Task<int> Add(int a, int b)
{
return a + b;
}
public async Task<Node> GetCyclicNodes()
{
Node nodeA = new Node() {Name = "Node A"}; …Run Code Online (Sandbox Code Playgroud)