I'm new to using Rx and I've been trying to re-write my MVC w/ Service Layer (NOT ASP!) to use this awesome new-fangled Rx. I have a class called Remote which encapsulates a NetworkStream. The Remote uses Rx to listen to bytes from the NetworkStream and once it works out it's received a full message worth of data, it decodes that data into an IMessage.
I get how I can read from the Stream continuously using Rx from inside the Remote, but how do I publish decoded IMessage from that stream to the outside world from the Remote? Am I supposed to use the classic evented style in C# and have the consumers of the events use Observable.FromEvent?
I only ask because I've read around that IObservable is not meant to be implemented anymore.
Am I supposed to use the classic evented style in C# and have the
consumers of the events use Observable.FromEvent?
If you're not positively forced to do so, do not make an API using C# style events. The IObservable<T> is a powerful, generic, widely supported interface which allows us to treat events as first class citizens while easily managing subscriptions. Even if your consumer isn't using Rx, they'll be able to understand and use IObservable<T> more easily than using C# events. What they do with those events is up to them, but the IObservable<T> abstraction is clearer and simpler.
I've read around that IObservable is not meant to be implemented anymore.
It reality, what we mean is that there's probably not reason to implement IObservable<T> on your own, because we have tools to create instances of that type for us.
We have Observable.Create(...) which allows us to create observables from scratch. We have different types of Subjects like Subject<T>, BehaviorSubject<T>, ReplaySubject<T>, etc, which can be used as proxies and allow us to multicast values to multiple consumers, and we have operators which allow us to transform/compose any IObservable<T> into another type or kind of IObservable<T>.
but how do I publish decoded IMessage from that stream to the outside world from the Remote?
You expose an IObservable<T> on your class / interface.
public interface IRemote
{
public IObservable<IMessage> Messages { get; }
}
You could implement this in any number of ways. First, you could make it so each subscription to Messages gets it's own subscription to your underlying logic...
public class Remote : IRemote
{
private IObservable<IMessage> _messages = ...;
public IObservable<IMessage> Message {
get {
return message;
}
}
}
Or you could make sure that there's only ever one subscription to the underlying logic...
public class Remote : IRemote
{
private IObservable<IMessage> _messages = ...;
private IObservable<IMessage> _refCountedMessages
= this._messages
.Publish()
.RefCount();
public IObservable<IMessage> Message {
get {
return this._refCountedMessages;
}
}
}
Or you could make the connection process extremely explicit in nature.
public interface IRemote
{
public IObservable<IMessage> Messages { get; }
public IDisposable Connect();
}
public class Remote : IRemote
{
private IObservable<IMessage> _messages = ...;
private IObservable<IMessage> _connectableMessages
= this._messages
.Publish();
public IObservable<IMessage> Message {
get {
return this._connectableMessages;
}
}
public IDisposable Connect()
{
return this._connectableMessages.Connect();
}
}
I assume you problem is similar to this question How to "reconstruct lines" of data read from SerialPort using Rx?
Instead of getting strings pushed at you that you then change into messages, you will get bytes. No problem, you can use the same WindowBy concept to slice up your sequence of bytes into windows that can then be translated/converted/mapped/whatever into your IMessage.
Building on Christopher Harris' answer. Here is an implementation of his proposed interfaces. The point here is to show that you can expose observable sequences that are just queries built on top of an underlying observable sequence. In this case the Messages sequence is just a query over the network sequence. With layering we get the level of abstraction that the consumer wants.
void Main()
{
var networkStream = new NetworkStream();
var remote = new Remote(networkStream);
remote.GetMessages().Dump("remote.GetMessages()");
}
// Define other methods and classes here
public class NetworkStream
{
//Fake getting bytes off the wire or disk
public IObservable<byte> GetNetworkStream()
{
var text = #"Line 1.
Hello line 2.
3rd and final line!";
return Observable.Zip(
UTF8Encoding.UTF8.GetBytes(text).ToObservable(),
Observable.Interval(TimeSpan.FromMilliseconds(100)),
(character, time)=>character);
}
}
public interface IMessage
{
string Content {get;}
}
public class Message : IMessage
{
public Message(string content)
{
Content = content;
}
public string Content {get; private set;}
}
public interface IRemote
{
IObservable<IMessage> GetMessages();
}
public class Remote : IRemote
{
private readonly NetworkStream _networkStream;
private readonly byte[] _delimiter = UTF8Encoding.UTF8.GetBytes(Environment.NewLine);
public Remote(NetworkStream networkStream)
{
_networkStream = networkStream;
}
public IObservable<IMessage> GetMessages()
{
return _networkStream.GetNetworkStream()
.WindowByExclusive(b => _delimiter.Contains(b))
.SelectMany(window=>window.ToArray().Select(bytes=>UTF8Encoding.UTF8.GetString(bytes)))
.Select(content=>new Message(content));
}
//TODO Add IDispose and clean up your NetworkStream
}
public static class ObservableEx
{
public static IObservable<IObservable<T>> WindowByExclusive<T>(this IObservable<T> input, Func<T, bool> isWindowBoundary)
{
return Observable.Create<IObservable<T>>(o=>
{
var source = input.Publish().RefCount();
var left = source.Where(isWindowBoundary).Select(_=>Unit.Default).StartWith(Unit.Default);
return left.GroupJoin(
source.Where(c=>!isWindowBoundary(c)),
x=>source.Where(isWindowBoundary),
x=>Observable.Empty<Unit>(),
(_,window)=>window)
.Subscribe(o);
});
}
}
Related
I have two interfaces, unaware of each other.
public interface IListener
{
event SignalEventHandler SignalReceived;
}
public interface IDevice
{
Task HandleSignalAsync();
}
Rather than making each listener call a device directly or pass listeners into device implementations, I'd like to keep them decoupled and define the flow separately. For example:
public class MyApplicationFlow
{
private readonly IListener _listener;
private readonly IDevice _device;
public MyApplicationFlow(IListener listener, IDevice device)
{
_listener = listener;
_device = device;
_listener.SignalReceived += ListenerOnSignalReceived;
}
private async void ListenerOnSignalReceived(object sender, SignalEventArgs args)
{
try
{
await _device.HandleSignalAsync();
// do more stuff in real scenario
args.ProgressReporter.ReportComplete();
}
catch (Exception ex)
{
args.ProgressReporter.ReportError(ex);
}
}
}
There could be several IDevice and IListener implementations passed into the flow.
The listeners and devices seem to follow the Adaptor pattern. But what about MyApplicationFlow?
A Mediator defines the interactions between components, but here the objects are different types and unaware of the parent class.
A Facade encapsulates several subsystems, but here the subsystems are not hidden; they are injected into the constructor.
I'm not even sure if this would be a Behavioural or Structural pattern.
Is there a common name for a class that defines the flow between objects? Something I can use as a suffix for the class names that follow this pattern e.g. Manager, Coordinator, Connector (preferably something already used in the .NET framework).
Or, as I can't find anything, am I barking up the wrong tree? Is there a better way to achieve this decoupling?
For one thing, based on your names it seems like you have your listener and device backwards. Meaning, you seem to be listening to a signal sent from the listener and sending it to the device which seems backwards. Listeners imply listening to signals not sending signals in my opinion.
But otherwise I think what you have here is just a message passing system. Rather than directly communicating together you have a message dispatcher which receives messages from one component and sends them off to another. If you expand on what you have there rather than having a single device and a single listener you could establish any number of connections. You would then queue incoming messages and dispatch them to listeners based on those connections.
interface IListener {
void send(ISender sender, IMessage message);
}
interface ISender { }
interface IMessage { }
interface IPending {
ISender from;
IMessage message;
}
class Dispatcher {
private Queue<IPending> messages = new Queue<IPending>();
private Dictionary<ISender, List<IListener>> connections = new Dictionary<ISender, List<IListener>>();
public void connect(ISender sender, IListener listener) {
if (connections[sender] == null) {
connections[sender] = new List<IListener>();
}
connections[sender].add(listener);
}
public void remove(ISender sender, IListener listener) { ... } // removes connection from connections
public void send(ISender from, IMessage message) {
messages.push({ from, message });
}
public void next() { // called in a loop, perhaps in a background thread
if (messages.peek()) {
var message = messages.pop();
foreach(var listener in connections[message.from]) {
listener.send(sender, message);
}
}
}
}
My first thought was it sounds like a variant of the observer pattern, except in your case the observer isn't directly observing. I found this variant called Event / Emitter / Target that sounds pretty close. https://github.com/millermedeiros/js-signals/wiki/Comparison-between-different-Observer-Pattern-implementations
Edit--I've actually changed my mind. This is pub-sub messaging. The IDevice classes are sending, the middle class is receiving the messages and the IListener is subscribing.
I have a external library used to exchange messages.
In this library I have an Object named Channel.
This is the result after decompiling the dll:
public class Channel
{
public State CurrentState { get { /*Only for code compiling, the value depend on the TCP Connection state.*/return State.ERROR; } }
public bool Send(string message)
{
//Some stuff with TCP connection.
return true;
}
public enum State
{
DISCONNECTED,
CONNECTED,
ERROR
}
}
Now in my code I use this Channel in a class for sending messages, the class looks like this :
public class ClientConnection
{
private Channel MyChannel;
public ClientConnection(Channel channel)
{
MyChannel = channel;
}
public bool Send(string message)
{
bool result = false;
if(MyChannel.CurrentState == Channel.State.CONNECTED)
{
result = MyChannel.Send(message);
}
return result;
}
}
So my goal is to test it, verifying that the method send is called, and checking that the arguments matches my input.
The problem here is that there is no interface and the method are not virtual, so mocking is not possible directly.
What did I do
I created a wrapper with overridable Property and Method like this :
public class ChannelWrapper
{
private readonly Channel channel;
public ChannelWrapper(Channel channel)
{
this.channel = channel;
}
public virtual Channel.State CurrentState { get { return channel.CurrentState; } }
public virtual bool Send(string message)
{
return channel.Send(message);
}
}
And changed in ClientConnection the type Channel to ChannelWrapper in the constructor and the property.
The Question
I fell that I should have created an extra interface that matches both Channel and ChannelWrapper, and mock using interface instead of overridable members.
And at the same time I really don't see the point of adding a new interface for nothing.
Is there any reason to prefer mocking an interface rather than a class with overridable members?
(I am thinking in term of performance mainly too).
The main reason you normally want to mock an interface rather than a concrete type is that, in the case of the concrete type, your mock will have bits and pieces of the actual implementation, potentially leading to unpredictable / undesired behaviour.
For example, the Send method on the Channel currently has "//Some stuff with TCP connection." inside it. What if the Channel class instantiates some web connections and stores them as fields? That means that your mock object now contains actual web connections, even though they might never be used. This might be more serious if we're talking database connections etc.
It may be that this isn't the case in your particular example, but you should think more that you've 'gotten away with it' this time, rather than that being the rule. These concerns mean it's normally much cleaner to mock an interface; you know that your mock object doesn't contain anything that you didn't put there in your test.
I would also see this very similar question: Mocking classes that aren't interfaces
I have an interface called IDataIO:
public interface IDataIO
{
event DataReceivedEvent DataReceived;
//.....more events,methods and properties
}
I also have multiple classes that implement this interface, namely UdpIO, TcpIO, SerialIO.
Now, I have an IO class that allows me to switch between different input/output hardware. Each instance of this class has a CurrentIODevice property, which could be one of SerialIO,UdpIO or TcpIO. When this property is assigned, i attach 1 or more handlers to the DataReceivedEvent so that my GUI is notified when incoming data is received, as well as other classes that need to be notified.
public class IO
{
IDataIO CurrentIODevice;
public IO()
{
SerialIO serial = new SerialIO();
TcpIO tcp = new TcpIO();
UdpIO udp = new UdpIO();
CurrentIODevice = serial;
}
}
I also have a IOManager class that holds multiple IO objects.
public class IOManager
{
List<IO> Ports = new List<IO>();
public IOManager()
{
Ports.Add(new IO());
Ports.Add(new IO());
}
Ports[0].CurrentIODevice = serial;
Ports[0].CurrentIODevice.DataReceivedHandler += MyGuiUpdate;
Ports[0].CurrentIODevice.DataReceivedHandler += MyDataProcessing;
}
My concern (its not an issue atm) is how I am going to change between different IDataIO interfaces at runtime.
What is the effect of, at runtime, performing the following statement:
//i know this is illegal but just to demonstrate
IOManager.Ports[0].CurrentIODevice = tcp;
Will the event handlers still be functioning (and correctly)?
Do i need to unassign the events before the CurrentIODevice is assigned, and then re-assign the handlers again after? If this is the case, I can see this approach getting quite messy, so if anyone has a better approach to this problem I'm all ears :)
No, your handlers will not work because they're attached to the old object. Interfaces provides...an interface to an object, see it as a kind of contract but they're not a different object themselves.
If you need to switch between different implementations of the interface (at run-time) and to keep all handlers working you have to have the same object reference for the interface itself, kind of strategy pattern (more or less).
In your case you may, for example, implement the IDataIO interface in a DataIO object. It'll expose a property (or a method, I think its intent is more clear) to switch between different implementations of that interface (serial, TCP or whatever). It'll be the only one object to attach an event handler to that interface (and it'll drop the handler when the concrete implementation will change). Users of that object will always see it, whatever it's the concrete implementation it's using.
Example
This is a small example to explain this concept. The generic interface is this:
interface IDataIO
{
void Write(byte[] data);
byte[] Read();
event EventHandler DataReceived;
}
This is the concrete implementation of IDataIO, other classes will use only this class directly:
sealed class DataIO : IDataIO
{
public void SetChannel(IDataIO concreteChannel)
{
if (_concreteChannel != null)
_concreteChannel.DataReceived -= OnDataReceived;
_concreteChannel = concreteChannel;
_concreteChannel.DataReceived += OnDataReceived;
}
public void Write(byte[] data)
{
_concreteChannel.Write(data);
}
public byte[] Read()
{
return _concreteChannel.Read();
}
public event EventHandler DataReceived;
private IDataIO _concreteChannel;
private void OnDataReceived(object sender, EventArgs e)
{
EventHandler dataReceived = DataReceived;
if (dataReceived != null)
dataReceived(this, e);
}
}
Finally some code for testing:
class Test
{
public Test()
{
_channel = new TcpIO();
_channel.DataReceived += OnDataReceived;
}
public void SetChannel(IDataIO channel)
{
_channel.SetChannel(channel);
// Nothing will change for this "user" of DataIO
// but now the channel used for transport will be
// the one defined here
}
private void OnDataReceived(object sender, EventArgs e)
{
// You can use this
byte[] data = ((IDataIO)sender).Read();
// Or this, the sender is always the concrete
// implementation that abstracts the strategy in use
data = _channel.Read();
}
private DataIO _channel;
}
Obviously you should consider the strategy pattern. I will post the code first and explain later:
public interface IDataIO
{
event DataReceivedEvent DataReceived;
//this the new added method that each IO type should implement.
void SetStrategy();
}
public class SerialIO : IDataIO
{
public void SetStrategy()
{
//put the code that related to the Serial IO.
this.DataReceivedHandler += MyGuiUpdate;
this.DataReceivedHandler += MyDataProcessing;
}
}
public class TcpIO : IDataIO
{
public void SetStrategy()
{
//put the code that related to the Tcp IO.
//I will not implement it because it is a demo.
}
}
public class UdpIO : IDataIO
{
public void SetStrategy()
{
//put the code that related to the Udp IO.
//I will not implement it because it is a demo.
}
}
public class IO
{
IDataIO port = new IDataIO();
public void SetIOType(IDataIO ioType)
{
this.port = ioType;
port.SetStrategy();
}
}
public class IOManager
{
List<IO> ports = new List<IO>();
SerialIO serial = new SerialIO();
TcpIO tcp = new TcpIO();
ports[0].SetIOType(serial);
ports[1].SetIOType(tcp);
}
The interface IDataIO define basics that the all the IO types should implement.
The SerialIO, TcpIO, UdpIO classes derived from IDataIO implement the method SetStrategy() to meet each of their own need.
The IO class owns a field(named port) refers to a IDataIO type, this field can be setted to a certain IO type during the runtime by calling the method SetIOType() defined in the IO
class. Once this method is being called, we know which type the 'port' field refers to, and
then call the SetStrategy() method, it will run the overrided method in one of the IO class.
The IOManager class is the client. when it needs a certain IO type, say SerialIO, it only need to new a IO class and call the SetIOType() method by passing a SerialIO class instance, and all the logic related to the SerialIO type will be setted automatically.
Hope my description can help you.
I am currently a good portion of the way through developing a socket based implementation of a generic communication "framework" that works between C# and Android.
Building the server and client has been easy enough. Nothing too technically challenging about that.
At this point the implementation contains 2 major components.
AndroidTcpListener (tcp socket class
that handles communication)
AndroidTcpServer (class that creates
an instance of the TcpListener and
handles the DataReceived (from the
TcpListener) when data is received)
Data is sent between the client and
the server using the standard XML
serializer (I may move to JSON at some
point but for the time being I have
settled on XML)
Where I seem to be completely stuck is how to handle and expose the data received.
I have tried using generics but no matter how I structure it, it seems that in the end I end up having to create an AndroidTcpServer<T> which then restricts me to a single datatype.
I have tried creating a CustomActivator class as such
class CustomActivator<T> where T : Serialization.ITcpSerializable<T>
{
public CustomActivator(String xmlTypeName, Byte[] data)
{
this.XmlTypeName = xmlTypeName;
this.Data = data;
}
public String XmlTypeName { get; set; }
public Byte[] Data { get; set; }
public T Activate()
{
T res = Activator.CreateInstance<T>();
using (MemoryStream stream = new MemoryStream(this.Data))
{
return res.Deserialize(XElement.Load(stream));
}
}
}
But again this seems to restrict me to implementing AndroidTcpServer<T>
I have tried creating an AndroidTcpEvent class which is structured as such
public class AndroidTcpEvent<T>
{
public AndroidTcpEvent() { }
public AndroidTcpEvent(String eventName, T data)
{
this.EventName = eventName;
this.Data = data;
}
public String EventName { get; set; }
public T Data { get; set; }
}
But the XMLSerializer seems to refuse to want to serialize it (I guess I could implement my own serializer but this is far from trivial and doesnt really solve how I will expose the data)
I have tried countless other approaches which all seem to hit a dead end somewhere.
So basically at this point I have (Inside of the AndroidTcpServer class a method as such
private void DataReceived(Object sender, TcpServerMessageReceivedEventArgs e)
{
//e.Data = Byte[] of XML serialized data of the message sent (Semantics are unimportant)
}
In conclusion I am hoping for some guidance on how one would typically handle exposing data received and actually creating instances of the data in such a generic framework and if there are any known patterns that can be used for this problem?
Obviously I could scrape all this generic implementation stuff and just create a custom implementation for whatever app I end up trying to build but I am doing this as both a learning exercise and something that I would like to release into the public for others to use.
Hopefully I have been clear but if anyone requires clarification on any aspect of this please let me know. Thanks in advance for everyones input.
First, I think the responsibilty of the server should end with raising the TcpServerMessageReceived event. It's task is to listen for incoming connections and receive data and then notify anyone who is interested.
Then you can attach your custom activator to that event maybe like this:
class CustomActivator<T> where T : Serialization.ITcpSerializable<T>
{
public void ListenTo(AndroidTcpServer server)
{
server.TcpServerMessageReceived += DataReceived;
}
private void DataReceived(object sender, TcpServerMessageReceivedEventArgs e)
{
T res = Activator.CreateInstance<T>();
using (MemoryStream stream = new MemoryStream(e.Data))
{
OnObjectReceived(res.Deserialize(XElement.Load(stream));
}
}
protected void OnObjectReceived(T obj)
{
var handler = ObjectReceived;
if (handler != null)
{
OnObjectReceived(this, new ObjectReceivedEventArgs(obj));
}
}
}
I'm not sure about the types of objects you send across the wire. If you can determine the type which is contained in the serialized xml before you actually need to deserialize the whole object then you can modify your CustomActivator so that it checks the type and ignores it if it is not its own T (hope that makes sense) and you attach activators for each type you can receive (maybe you can use reflection to attach all types implementing the ISerializable interface automatically).
Update: If you can guess the type from the incoming data you could do something like this:
class GenericActivator
{
public void ListenTo(AndroidTcpServer server)
{
server.TcpServerMessageReceived += DataReceived;
}
private void DataReceived(object sender, TcpServerMessageReceivedEventArgs e)
{
var t = Type.GetType(GuessTypeName(e.Data));
var res = Activator.CreateInstance(t) as typeof(ITcpSerializable<>).MakeGenericType(t);
using (MemoryStream stream = new MemoryStream(e.Data))
{
OnObjectReceived(res.Deserialize(XElement.Load(stream));
}
}
protected void OnObjectReceived(object obj)
{
var handler = ObjectReceived;
if (handler != null)
{
OnObjectReceived(this, new ObjectReceivedEventArgs(obj));
}
}
}
You could also add a type registry to GenericActivator where you can register listeners for each type like this:
class GenericActivator
{
private Dictionary<Type, List<Action<object>> _TypeListeners;
public void Register<T>(Action<object> objectReceived)
{
List<Action<object>> listeners;
if (!_TypeListeners.TryGet(typeof(T), out listeners)
{
listeners = new List<Action<object>>();
}
listeners.Add(objectReceived);
}
}
And then only call the listeners for the type received. Makes the assumption that GuessTypeName works reliably.
I have a class, ClassA that uses a client I wrote to send text messages, TextClient, to send some text messages via a call to the static method
TextClient.Send(string text, string destination)
// where destination is a phone number
However, I also have a mail client class, MailClient, which sends emails with the same signature:
MailClient.Send(string text, string destination)
// where destination is an email address
I would like to "inject" which of these clients should be used - is this possible?
(Note: I'm aware of problems that might arise when there are entirely different rules for what values destination can hold and be considered valid, but the values are fetched from someplace else, so this class doesn't need to bother. That's why I want to abstract this away in the first place.)
Basically, get rid of the static methods. Create an interface (IMessageClient) and then two implementations (TextClient and MailClient) with instance methods implementing the interface. Then you can inject the appropriate IMessageClient into the rest of the application with ease.
You certainly can use delegates to avoid creating the interface here - but I would definitely change to using interfaces instead:
The names involved (the interface name, method name and parameter names) convey information when you're using them
It allows for multiple methods in the same interface
It prevents methods which happen to have the same argument types but a completely unrelated meaning from being used accidentally
Sure, make your clients implement some sending interface.
public interface IMessageClient
{
public void Send(string text, string destination);
}
public class TextClient : IMessageClient
{
public void Send(string text, string destination)
{
// send text message
}
}
public class MailClient : IMessageClient
{
public void Send(string text, string destination)
{
// send email
}
}
public class ClassA
{
private IMessageClient client;
public ClassA(IMessageClient client)
{
this.client = client;
}
}
Same as Jon Skeet's answer, but he beat me by not typing out the code.
It's generally better to avoid static classes when designing such services because it makes it more challenging to decouple from other code.
If you have control over the design and implementation of the TextClient and MailClient classes, I would suggest considering making them singleton instance classes rather than static classes. You could then implement a common interface IMessageSender (see below) in both and pass that as an instance to the object that needs to make the call.
public interface IMessageSender
{
void Send( string message, string destination );
}
public class TextClient : IMessageSender { ... }
public class MailClient : IMessageSender { ... }
If you don't have control over the implementation of those classes (or can't change them at this point), you could pass a delegate into the object that needs to make the call:
class SomeConsumer
{
private Action<string,string> m_SendDelegate;
public SomeConsumer( Action<string,string> sendDelegate )
{
m_SendDelegate = sendDelegate;
}
public DoSomething()
{
// uses the supplied delegate to send the message
m_SendDelegate( "Text to be sent", "destination" );
}
}
var consumerA = new SomeConsumer( TextClient.Send ); // sends text messages
var consumerB = new SomeConsumer( MailClient.Send ); // will send emails
Don't make the methods static, create an interface with the Send()method and implement this interface on TextClient and MailClient. Now you can just inject an instance using the interface.
If it is not possible to make the methods non-static you can just write to thin wrappers around the static method call both implementing the said interface.
I would have thought so. If you have an interface as such
public interface ISender
{
void Send(string text, string destination);
}
Then just use dependency injection to pick up which sender to use.