C# 优先订阅调用

C# 优先订阅调用,c#,.net,system.reactive,C#,.net,System.reactive,我有一个单一的可观察的信息序列。有一组订阅者可以处理这些消息。每个订阅服务器都有一个执行优先级。每个消息必须由从当前订阅的订阅者列表中选择的最高优先级订阅者处理一次。订阅者不断地订阅/取消订阅序列,因此在构建序列时,我们不知道订阅者的数量和优先级。使用rx是否是一种可能/可行的解决方案 举例说明: public class Message { public string Value { get; set; } public bool IsConsumed { get; set;

我有一个单一的可观察的信息序列。有一组订阅者可以处理这些消息。每个订阅服务器都有一个执行优先级。每个消息必须由从当前订阅的订阅者列表中选择的最高优先级订阅者处理一次。订阅者不断地订阅/取消订阅序列,因此在构建序列时,我们不知道订阅者的数量和优先级。使用rx是否是一种可能/可行的解决方案

举例说明:

public class Message
{
    public string Value { get; set; }
    public bool IsConsumed { get; set; }
}

var subject = new Subject<Message>();
var sequence = subject.Publish().RefCount();

Action<Message, int> subscriber = (m, priority) =>
{
    if (!m.IsConsumed)
    {
        m.IsConsumed = true;
        Trace.WriteLine(priority);
    }
};

var s2 = sequence.Priority(2).Subscribe(m => subscriber(m, 2));
var s1 = sequence.Priority(1).Subscribe(m => subscriber(m, 1));

subject.OnNext(new Message()); // output: 1

s1.Dispose();
subject.OnNext(new Message()); // output: 2
公共类消息
{
公共字符串值{get;set;}
公共布尔值为{get;set;}
}
var subject=新的subject();
变量序列=subject.Publish().RefCount();
行动订户=(m,优先级)=>
{
如果(!m.IsConsumed)
{
m、 IsConsumed=真;
Trace.WriteLine(优先级);
}
};
VARS2=序列。优先级(2)。订阅(m=>subscriber(m,2));
var s1=序列。优先级(1)。订阅(m=>subscriber(m,1));
subject.OnNext(新消息());//产出:1
s1.Dispose();
subject.OnNext(新消息());//产出:2

使此解决方案起作用的缺失部分是Rx库中不存在的优先级方法。

这是一个非常有趣的问题

因此,首先:我不知道有任何内在的Rx运营商可以实现类似于此
优先级
扩展所需的“路由”效果

这就是说,今天午餐时我在LINQPad玩,想出了一个(非常)骇人的概念证明,似乎很管用:

首先,你的消息类

public class Message
{
    public string Value { get; set; }
    public bool IsConsumed { get; set; }
}
接下来,扩展方法包装类:

public static class Ext
{    
    public static PrioritizedObservable<T> Prioritize<T>(this IObservable<T> source)
    {
        return new PrioritizedObservable<T>(source);
    }
}
公共静态类Ext
{    
公共静态优先级可维护优先级(此IObservable源)
{
返回新的可服务(源);
}
}
这是什么可维护的

公共类可服务
:IObservable、IObserver、IDisposable
{
私有IObservable\u源;
私人ISubject_中介;
专用IList_路由器;
公共可服务(IObservable源)
{
//确保我们不会意外地重复订阅
//到底层源
_source=source.Publish().RefCount();
//从源到内部路由器的代理
_中间层=Subject.Create(此,_源);
_来源.认购(_中间人);
//按优先科目排列
_路由器=新列表();
}
公共空间处置()
{
_中间=空;
foreach(路由器中的var条目)
{
entry.Item2.Dispose();
}
_router.Clear();
}
私有ISubject GetFirstListener()
{
//在我们的路由器中获取第一个主题
//按优先级排序
return\u router.OrderBy(tup=>tup.Item1)
.Select(tup=>tup.Item2)
.FirstOrDefault();
}
void IObserver.OnNext(T值)
{
//将值传递给第一行
var nextListener=GetFirstListener();
if(nextListener!=null)
nextListener.OnNext(值);
}
void IObserver.OnError(异常错误)
{
//将错误传递给第一行
var nextListener=GetFirstListener();
if(nextListener!=null)
nextListener.OnError(错误);
}
void IObserver.OnCompleted()
{
var nextListener=GetFirstListener();
if(nextListener!=null)
nextListener.OnCompleted();
}
公共IDisposable订阅(IObserver obs)
{
返回优先级订阅(1,obs);
}
公共IDisposable PrioritySubscribe(int优先级,IObserver obs)
{
var sub=新主题();
var订户=子订户(obs);
var entry=Tuple.Create(优先级,子级);
_添加(条目);
_中介人。认购(子);
返回一次性。创建(()=>
{
subscriber.Dispose();
_移除(入口);
});
}
}
和一个测试线束:

void Main()
{
    var subject = new Subject<Message>();
    var sequence = subject.Publish().RefCount().Prioritize();

    Action<Message, int> subscriber = (m, priority) =>
    {
        if (!m.IsConsumed)
        {
            m.IsConsumed = true;
            Console.WriteLine(priority);
        }
    };

    var s3 = sequence.PrioritySubscribe(3, Observer.Create<Message>(m => subscriber(m, 3)));
    var s2 = sequence.PrioritySubscribe(2, Observer.Create<Message>(m => subscriber(m, 2)));
    var s1 = sequence.PrioritySubscribe(1, Observer.Create<Message>(m => subscriber(m, 1)));
    var s11 = sequence.PrioritySubscribe(1, Observer.Create<Message>(m => subscriber(m, 1)));

    subject.OnNext(new Message()); // output: 1

    s1.Dispose();
    subject.OnNext(new Message()); // output: 1
    s11.Dispose();

    subject.OnNext(new Message()); // output: 2
    s2.Dispose();
    subject.OnNext(new Message()); // output: 3

    sequence.Dispose();

}
void Main()
{
var subject=新的subject();
var sequence=subject.Publish().RefCount().priority();
行动订户=(m,优先级)=>
{
如果(!m.IsConsumed)
{
m、 IsConsumed=真;
控制台写入线(优先级);
}
};
var s3=sequence.PrioritySubscribe(3,Observer.Create(m=>subscriber(m,3));
var s2=sequence.PrioritySubscribe(2,Observer.Create(m=>subscriber(m,2));
var s1=sequence.PrioritySubscribe(1,Observer.Create(m=>subscriber(m,1));
var s11=sequence.PrioritySubscribe(1,Observer.Create(m=>subscriber(m,1));
subject.OnNext(新消息());//输出:1
s1.Dispose();
subject.OnNext(新消息());//输出:1
s11.处置();
subject.OnNext(新消息());//输出:2
s2.Dispose();
subject.OnNext(新消息());//输出:3
sequence.Dispose();
}

你真是天才!非常感谢你!
void Main()
{
    var subject = new Subject<Message>();
    var sequence = subject.Publish().RefCount().Prioritize();

    Action<Message, int> subscriber = (m, priority) =>
    {
        if (!m.IsConsumed)
        {
            m.IsConsumed = true;
            Console.WriteLine(priority);
        }
    };

    var s3 = sequence.PrioritySubscribe(3, Observer.Create<Message>(m => subscriber(m, 3)));
    var s2 = sequence.PrioritySubscribe(2, Observer.Create<Message>(m => subscriber(m, 2)));
    var s1 = sequence.PrioritySubscribe(1, Observer.Create<Message>(m => subscriber(m, 1)));
    var s11 = sequence.PrioritySubscribe(1, Observer.Create<Message>(m => subscriber(m, 1)));

    subject.OnNext(new Message()); // output: 1

    s1.Dispose();
    subject.OnNext(new Message()); // output: 1
    s11.Dispose();

    subject.OnNext(new Message()); // output: 2
    s2.Dispose();
    subject.OnNext(new Message()); // output: 3

    sequence.Dispose();

}