I am trying to pass messages between several classes that communicate through interface. However, as I like to go as generic as possible, I ran into problems because the message type of incoming messages may be different from the outgoing type. I pasted some code to make it clearer.
The code below does not compile because the interface implementation passes a different type than the type of the blocking collection to which it is supposed to add incoming messages. I want to be able to send types potentially different from incoming types (incoming types obviously always match the type of the elements in the blocking collection). Can I somehow get around any sort of casting or parsing even if that means I need to redesign my interface or class?
I am still quite fresh when it comes to working with interfaces and struggled with recursions, stack overflow errors, and the like. So, if you have suggestions what I can improve design wise or just a quick fix then please help me to learn. Am very eager to understand how to implement a better pattern.
Thanks
public interface IClientMessaging
{
void MessagePassing<U>(U message);
}
public class InProcessMessaging<T> : IClientMessaging
{
private Dictionary<Type, List<IClientMessaging>> Subscriptions;
public BlockingCollection<T> MessageBuffer;
public InProcessMessaging(Dictionary<Type, List<IClientMessaging>> subscriptions)
{
//Setup Message Buffer
MessageBuffer = new BlockingCollection<T>();
//Subscribe
Type type = typeof(T);
if (subscriptions.Keys.Contains(type))
{
subscriptions[type].Add(this);
}
else
{
subscriptions.Add(type, new List<IClientMessaging>());
subscriptions[type].Add(this);
}
Subscriptions = subscriptions;
}
public void SendMessage<U>(U message)
{
//Send message to each subscribed Client
List<IClientMessaging> typeSubscriptions = Subscriptions[typeof(U)];
foreach (IClientMessaging subscriber in typeSubscriptions)
{
subscriber.MessagePassing<U>(message);
}
}
public T ReceiveMessage()
{
return MessageBuffer.Take();
}
public bool ReceiveMessage(out T item)
{
return MessageBuffer.TryTake(out item);
}
//Interface Implementation
public void MessagePassing<U>(U message)
{
MessageBuffer.Add(message); //<-"Cannot convert from U to T" [this is because I want
//to send messages of a different type than the receiving type]
}
}
I’m struggling to understand your goal here, but perhaps
MessagePassing<U>(U message)should beMessagePassing(U message)andinterface IClientMessagingshould beinterface IClientMessaging<U>.Then
InProcessMessaging<T, U> : IClientMessaging<U>– but I don’t see whyInProcessMessagingimplementsIClientMessagingAND manages subscriber lists ofIClientMessaging. Seems to me that one class would manage the subscribers and another IS a subscriber (IClientMessaging).You say
UandTare different types. Well – are they related? Is one wrapper for the other? Sounds like maybeUis either a wrapper forT, a generic class itself that contains theTbut adds extra info. In that case,void MessagePassing<T>(Wrapper<T> message);UPDATES
Based on the comments so far …
But rename those to:
and add:
Then:
Yes, this would use reflection to invoke
IConsumer<TConsumed>.Consume(). Or you can leave off the generics and just useobjectas your types. Better yet,IClientMessagecan have aConsume(object message)which in your implementation can ensure thatobjectis aTConsumedbefore attempting to process it.You could otherwise create direct client-to-client links through C# events, but you seem intent on a central dispatcher. It is the central dispatchers need to keep track of these different and unbounded number of types that is either going to require reflection OR be unaware of the types being passed (as described in the previous paragraph)
You should look at Reactive Extensions and the Observer pattern for ideas as well.
I removed my comments because it was getting too chatty.