Linq 使用reactive合并分块消息

Linq 使用reactive合并分块消息,linq,c#-4.0,system.reactive,Linq,C# 4.0,System.reactive,因此,我试图使用reactive来重新组合由ID标识的分块消息,但在终止最终的可观察对象时遇到了问题。我有一个消息类,它由Id、总大小、有效负载、区块编号和类型组成,并具有以下客户端代码: 我需要计算运行时要接收的消息数 (from messages in (from messageArgs in Receive select Serializer.Deserialize<Message>(new MemoryStream(Encoding.UTF8.GetBytes(mess

因此,我试图使用reactive来重新组合由ID标识的分块消息,但在终止最终的可观察对象时遇到了问题。我有一个消息类,它由Id、总大小、有效负载、区块编号和类型组成,并具有以下客户端代码:

我需要计算运行时要接收的消息数

(from messages in
   (from messageArgs in Receive select Serializer.Deserialize<Message>(new MemoryStream(Encoding.UTF8.GetBytes(messageArgs.Message))))
 group messages by messages.Id into grouped select grouped)
.Subscribe(g =>
{
    var cache = new List<Message>();
    g.TakeWhile((int) Math.Ceiling(MaxPayload/g.First().Size) < cache.Count)
      .Subscribe(cache.Add, 
    _ => { /* Rebuild Message Parts From Cache */ });
});
首先,我创建一个分组的可观察消息,根据它们的唯一ID过滤消息,然后我尝试缓存每个组中的所有消息,直到我收集了所有消息,然后对它们进行排序并将它们放在一起。上述情况似乎阻碍了g.First的发展

我需要一种方法来计算的数字,从第一个或任何消息来通过,但我有困难这样做。有什么帮助吗?

首先是一个阻塞运算符,否则它如何返回T而不可观察

我认为使用Scan随着时间的推移构建聚合可能是您所需要的。使用扫描,可以在生成器对象中隐藏消息重新构造的状态

MessageBuilder.IsComplete在收到的所有消息大小达到MaxPayload或满足您的任何要求时返回true。Build然后返回重建的消息

我还将消息构建代码移动到SelectMany中,它将构建的消息保存在monad中

很抱歉将代码重新格式化为扩展方法,我发现很难读/写混合LINQ语法

Receive
    .Select(messageArgs => Serializer.Deserialize<Message>(
        new MemoryStream(Encoding.UTF8.GetBytes(messageArgs.Message))))
    .GroupBy(message => message.Id)
    .SelectMany(group =>
    {
        // Use the builder to "add" message parts to
        return group.Scan(new MessageBuilder(), (builder, messagePart) =>
        {
            builder.AddPart(messagePart);

            return builder;
        })
        .SkipWhile(builder => !builder.IsComplete)
        .Select(builder => builder.Build());
    })
    .Subscribe(OnMessageReceived);

很酷的解决方案,我总是忘记GroupBy这确实是一个非常酷的解决方案,我显然需要研究LINQ中提供的大量选项。非常感谢