Some of my classes send and receive message of the same type and I want them not to react on the messages they've sent.
The only way I see now is explicit sender's call to Unregister() prior sending the message and then calling Register() again after message is sent. This is fine but it requires quite a bit of boilerplate code.
It would be nice to have something like Messenger.SendExceptSender(msg,sender) where messenger ignores the sender if finds it in the list of the recipients.
Does IMessenger support this some way?
As far as I see, that's not possible. Neither the interface nor the implementation have facilities for this as they don't even know who the sender is.
The easiest approach would be to add the sender as a property to the message. This would greatly reduce the boilerplate code and would be safer than Register and Unregister in multi-threaded scenarios.
You could register your message like so:
messenger.Register(this, m => {
if(m.Sender == this)
return;
YourMessageHandler(m);
} );
If this is a common scenario on your code you could even create an interface or base class for that Sender property and extension methods for Register and Send that handle it.
You can include token with your message and where you want to register you also include token in registration routine.
Related
I have a method called ProcessMessage(IMessage message, IMessageHandler<IMessage> messageHandler). The containing class has a collection of Message handlers: List<IMessageHandler<IMessage>> messageHandlers.
I need to pull out a specific Message Handler from my List<IMessageHandler<IMessage>> to process any given message correctly.
ProcessMessage(message, this.messageHandlers.SingleOrDefault
(
mh => mh.GetType().GetGenericArguments()[0].GetType() == message.GetType()
));
My problem occurs when I try to unit test this function. I need to populate my List<IMessageHandler<IMessage>> with mocked up message handlers. Unfortunately, GetType() is non-virtual and I get the standard "Invalid setup on a non-virtual member" error from moq. Or a better way to setup my test data?
Is there a better way to architect this so that I don't have to use a non-virtual method (ie: GetType) to do that comparison?
You should never base your unit test on implementation details, you should test the functionality of your code instead.
The fact that your code is using GetType() method is an implementation detail only. What is more important is that your code should be able to find the correct message handler for a provided message.
To test the functionality of your code, you can create a few manual implementation of the IMessage and IMessageHandler<IMessage> interfaces. A few test cases worth covering:
The correct message handler gets invoked
There are multiple message handlers for a certain message
There are no message handlers for a certain message
As far as I can understand from MassTransit's documentation and API, this is the only way to register a method message handler:
IServiceBus.SubscribeHandler<T>(Action<T> handler)
However, I'd like to register handlers using reflection based on attributes, so Ideally I need something like this:
IServiceBus.SubscribeHandler(Type messageType, Action<object> handler)
Does anything like that exist, or is there a way to achieve it?
MassTransit requires the type information "statically" in the call. There's no way around that.
You can however make calls to the SubscribeHandler<T> via reflection and pass in the generic's type information. A extension method to do this would work great, and could likely have the exact same signature you're looking for above.
I have the following scenario:
I have a QueueReader class that will be reading messages from a queue. I also have some Senders like EmailSender and SMSSender, that will send these messages to clients using Email or SMS respectively. In the future more Senders can be added.
I can think of two ways of doing this and I am not sure which would be more beneficial.
Factory Pattern:
I can have a SenderManager that will use a SenderFactory to create the appropriate sender and then call its Send() method.
So the QueueReader upon reading a message will call the SenderManager's Send() which will do the following:
IMySender sender = SenderFactory.CreateSender()
sender.Send()
//I have the information to create the proper Dispatcher in the
//factory based upon the message but I have omitted it for brevity.
So, now if I have to add a new sender, I won't have to change the QueueReader or the SenderManager. I will just add the new Sender and modify the SenderFactory.
Observer Pattern
In contrast to the above, I can have the QueueReader class implement an Event for NewMessage. Then have all my Senders subscribe to this event. The Sender will have access to the information that was in the Factory above to know if the message is for them.
The benefit of this would be any new Sender will simply have to subscribe to the event.
Now that I have written all of this down, I think the Observer Pattern is the cleaner approach...
However, if anyone has any insight or suggestion, please do share.
Thanks!
I would use an hybrid approach:
SenderManager (The observer) would listen to the incoming messages and pick the right sender (or ask the SenderFactory to create one if needed). This has 2 benefits:
First, you have control over which sender you pick (You don't need to expose the SenderManager class) avoiding attack of type ManInTheMiddle. This is particularly important if you are going to expose an API for other developers to implement their own senders.
Second, you can implement a sort of Garbage Collector and dispose of the sender that are no longer needed, instead of having multiple senders that are instantiated and monitoring your stream for nothing.
You will need some kind of registration function to register the senders against the SenderManger.
If you use an ObserverPattern, don't forget to implement a default sender (can be a log system) in order to handle the unwanted messages.
Factory pattern will be fine if you want to create instance based on certain criteria.
If you are sure that you will use either SMS or Email sender then you can consider using Dependency Injection as well and let IMySender be resolved on runtime using any DI container. For example, StructureMap.
I am not sure about observer pattern, seems to be a bit complex.
Is there a way in NServiceBus to replace the IHandleMessages<> handler with my own version of this interface that isnt strongly tied to NServiceBus?
I have found ways of replacing the event/command marker interfaces (Via NServiceBus 3 Unobtrusive syntax) but no way of doing the same for the actual handler. I am trying to do this to remove the coupling between my handlers and NServiceBus.
I found it possible with little code required:
1) Create a generic class implementing IHandleMessages<TMessage> and implement the Handle method making it find or create the correct instance of your custom handler (from DI container, static registry etc.). In this example assume that you've got MyCustomHandler class with void HandleMessageMyWay(object message) method accepting any message type:
public class MessageHandlerAdapter<TMessage>
: IHandleMessages<TMessage>
{
public void Handle(TMessage message)
{
new MyCustomHandler().HandleMessageMyWay(message);
}
}
It's an open generic, so NServiceBus won't discover it as a valid handler, because you need a closed generic (with TMessage being a concrete type like MyMessage1) to be seen by NServiceBus as a handler for the concrete type.
2) Implement ISpecifyMessageHandlerOrdering. In it's SpecifyOrder method make (at runtime) a closed generic adapter type for each message type which you want to support:
public class MessageHandlerAdapterLister : ISpecifyMessageHandlerOrdering
{
public void SpecifyOrder(Order order)
{
//You would normally iterate through your message types (over DI registry or some other registry of messages):
var adapterType1 = typeof(MessageHandlerAdapter<>).MakeGenericType(typeof(MyMessage1));
var adapterType2 = typeof(MessageHandlerAdapter<>).MakeGenericType(typeof(MyMessage2));
order.Specify(new[] { adapterType1, adapterType2 });
}
}
ISpecifyMessageHandlerOrdering instances are automatically discovered by NServiceBus. These are normally used to specify order for handler types which are discovered by NServiceBus. Apparently when you specify types which have not been discovered (like our closed generic adapter types made at runtime), it will simply add them to the registry.
That's all you need. NServiceBus will route MyMessage1 and MyMessage2 through the open generic IHandleMessages<TMessage> which then delegates handling to your custom class.
The reason for the NServiceBus 3.0 Unobtrusive Mode (see Andreas Ohlund's article on this) is that event definitions shared between multiple services can get into trouble if different endpoints are running different versions of NServiceBus, because the version on NServiceBus.dll that you are taking a dependency on will not match.
This argument does not hold water with the message handlers (the classes implementing IHandleMessages) themselves. There's no sharing of handlers. The message handler is, by definition, coupled to NServiceBus.
This seems to not be possible with NServiceBus.
The way i made this as unobtrusive as possible was to create a NServiceBus proxy to forward messages to my own bus, this kept the NServiceBus references out of most of my projects.
I have to take some pre-defined WSDL's (I do not control these), and expose them on our device to reply to various SOAP/UPnP requests.
Anyway, I have all of this working, but the problem comes through because I have one service that could be requested on any number of channels. I'll explain:
[System.ServiceModel.ServiceContractAttribute(Namespace="urn:some:namespace:1", ConfigurationName="myInterface")]
public interface myInterface
{
[System.ServiceModel.OperationContractAttribute(Action="urn:some:namespace:1#GetConfiguration", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
[return: System.ServiceModel.MessageParameterAttribute(Name="config")]
MyConfigurationResponse GetConfiguration(MyConfigurationRequest request);
}
Basically, what I'm attempting to do (I realize this syntax is completely wrong but I think it will get the point across) is this:
[System.ServiceModel.ServiceContractAttribute(Namespace="urn:some:namespace:{channelNumber}", ConfigurationName="myInterface")]
public interface myInterface
{
[System.ServiceModel.OperationContractAttribute(Action="urn:some:namespace:{channelNumber}#GetConfiguration", ReplyAction="*")]
[System.ServiceModel.XmlSerializerFormatAttribute()]
[return: System.ServiceModel.MessageParameterAttribute(Name="config")]
MyConfigurationResponse GetConfiguration(MyConfigurationRequest request, String channelNumber);
}
I simply would like some portion of my original Action message passed in as a parameter to the method I'm implementing.
The only other way I have thought of that I could implement this, would be to specify some other method, we'll call it Dispatcher with the Action="*", and then manually parse the received action using OperationContext.Current.IncomingMessageHeaders.Action. This just seems like a really shady way of doing things. I'm certain that the main roadblock here is my inexperience with WCF.
Any help you're able to provide would be much appreciated.
Thanks,
The easiest way to manage this is to create a generic message handler. The contract would look something like this:
[ServiceContract(SessionMode = SessionMode.Allowed)]
public interface ICatchAll
{
[OperationContract(IsOneWay = false, Action = "*", ReplyAction = "*")]
Message ProcessMessage(Message message);
}
The idea is that you create a "router" method for your service along the lines of this article. You'll still need to create the individual channel service contracts to shape the soap message to be received & returned but you'll have the client endpoint go to your "router" service endpoint. You may be able to do something along these lines with the new WCF 4 RoutingService if you create a separate instance of each channel service contract.
The only generalization of action method is the wild card * and it is usually used with both input and output as generic Message.
There is a way to customize whole behavior of the operation selection and parameters definition and filling. You can check following interfaces:
IDispatchOperationSelector is used to select operation based on incomming data
IOperationInvoker is used to allocate parameters and invoke the operation selected by IDispatchOperationSelector
IDispatchMessageFormatter is used to fill parameters for the operation to allocation slots prepared by IOperationInvoker
You probably don't need to implement them all but they will allow you to customize the behavior in any way you need. For example of custom selector and formatter check MSDN samples for example of custom invoker check this article. Anyway this whole infrastructure coding will just move your Action parsing to some WCF internals but you will still have to do that to get it as operation parameter.