Created
January 29, 2024 21:59
-
-
Save paulrobello/d8e0ad6c54578ddfa1bc078d100bd580 to your computer and use it in GitHub Desktop.
Websocket message subscription filter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
namespace Websocket | |
{ | |
public interface IWsMessageFilterPredicate | |
{ | |
bool Evaluate(IWsMessage msg); | |
} | |
// This filter will always evaluate to true | |
public class WsNullFilter : IWsMessageFilterPredicate | |
{ | |
public bool Evaluate(IWsMessage msg) | |
{ | |
return true; | |
} | |
} | |
// Evaluates to true if all predicates evaluate to true | |
public class WsAndFilter : IWsMessageFilterPredicate | |
{ | |
private readonly List<IWsMessageFilterPredicate> _predicates = new(); | |
public bool Evaluate(IWsMessage msg) | |
{ | |
return _predicates.All(predicate => predicate.Evaluate(msg)); | |
} | |
public WsAndFilter AddPredicate(IWsMessageFilterPredicate predicate) | |
{ | |
_predicates.Add(predicate); | |
return this; | |
} | |
public WsAndFilter() | |
{ | |
} | |
public WsAndFilter(IWsMessageFilterPredicate predicate) | |
{ | |
_predicates.Add(predicate); | |
} | |
} | |
// Evaluates to true if any predicate evaluates to true | |
public class WsOrFilter : IWsMessageFilterPredicate | |
{ | |
private readonly List<IWsMessageFilterPredicate> _predicates = new(); | |
public bool Evaluate(IWsMessage msg) | |
{ | |
return _predicates.Any(predicate => predicate.Evaluate(msg)); | |
} | |
public WsOrFilter AddPredicate(IWsMessageFilterPredicate predicate) | |
{ | |
_predicates.Add(predicate); | |
return this; | |
} | |
public WsOrFilter() | |
{ | |
} | |
public WsOrFilter(IWsMessageFilterPredicate predicate) | |
{ | |
_predicates.Add(predicate); | |
} | |
} | |
// Evaluates to true if the predicate evaluates to false | |
public class WsNotFilter : IWsMessageFilterPredicate | |
{ | |
private readonly IWsMessageFilterPredicate _predicate; | |
public bool Evaluate(IWsMessage msg) | |
{ | |
return !_predicate.Evaluate(msg); | |
} | |
public WsNotFilter(IWsMessageFilterPredicate predicate) | |
{ | |
_predicate = predicate; | |
} | |
} | |
// Evaluates to true if the message type matches | |
public class WsMsgTypeFilter : IWsMessageFilterPredicate | |
{ | |
private readonly string _msgType; | |
public bool Evaluate(IWsMessage msg) | |
{ | |
return _msgType == null || msg.MsgType == _msgType; | |
} | |
public WsMsgTypeFilter(string topic) | |
{ | |
_msgType = topic; | |
} | |
} | |
// Evaluates to true if the topic matches | |
public class WsMessageTopicFilter : IWsMessageFilterPredicate | |
{ | |
private readonly string _topic; | |
public bool Evaluate(IWsMessage msg) | |
{ | |
return _topic == null || msg.Topic == _topic; | |
} | |
public WsMessageTopicFilter(string topic) | |
{ | |
_topic = topic; | |
} | |
} | |
// Evaluates to true if the request id matches | |
public class WsMessageRequestIdFilter : IWsMessageFilterPredicate | |
{ | |
private readonly string _requestId; | |
public bool Evaluate(IWsMessage msg) | |
{ | |
return _requestId == null || msg.RequestId == _requestId; | |
} | |
public WsMessageRequestIdFilter(string requestId) | |
{ | |
_requestId = requestId; | |
} | |
} | |
// Invokes callback if all predicates evaluate to true | |
public class WsMessageFilter | |
{ | |
private readonly WsAndFilter _predicates = new(); | |
// The callback will be invoked when the filter evaluates to true | |
private Action<WsMessage> _callback; | |
// If Once is true, the callback will be invoked at most once before being removed from the list of subscribers | |
public bool Once { get; private set; } | |
// Returns true if all predicates evaluate to true | |
public bool Evaluate(IWsMessage msg) => _predicates.Evaluate(msg); | |
public WsMessageFilter AddPredicate(IWsMessageFilterPredicate predicate) | |
{ | |
_predicates.AddPredicate(predicate); | |
return this; | |
} | |
public WsMessageFilter SetCallback<T>(Action<T> callback) where T : WsMessage | |
{ | |
_callback = msg => callback(msg as T); | |
return this; | |
} | |
private void InvokeCallback(WsMessage msg) | |
{ | |
_callback?.Invoke(msg); | |
} | |
public WsMessageFilter SetOnce(bool once) | |
{ | |
Once = once; | |
return this; | |
} | |
public WsMessageFilter() | |
{ | |
} | |
public WsMessageFilter(Action<WsMessage> callback, bool once = false) | |
{ | |
_callback = callback; | |
Once = once; | |
} | |
public bool InvokeIfMatch(WsMessage msg) | |
{ | |
if (!Evaluate(msg)) return false; | |
InvokeCallback(msg); | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment