NServiceBus custom message handler type - c#

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.

Related

How to extend a class with events

I´ve written a library, that is implementing a third party protocol. This protocol is following the publish-subscribe pattern (over MQTT). So basically for every message, I have a publisher method and an event, that is fired when a message of certain type arrives. Now, for my needs, I want to extend this protocol with my own messages. But also, I´ve laid down these two requirements:
Keep the basic library clean only following the protocol architecture
Extend somehow the basic library with my own messages, so in code, you can use the original messages along with my own messages in one class.
I am thinking about two options here. First is to use C# extensions methods. The big advantage I see in this option is the ability to use only one class with the standard protocol architecture and in case of need, one can add a reference to the assembly with the extensions and use the extended library with my proprietary messages. No refactoring needed. On the other hand, extensions are only static methods and don´t support events.
The second option I see is to inherit a new class and use the basic library as a base. The huge advantage of this is, that I can do everything I want in the derived class. But if one decides to use the extended library after some coding, the refactoring is needed. Here I was considering to name the inherited class with the same name as the base class, but in a different namespace, so in case of need, one can change the using statement form
using Hermes
into
using Hermes.Extended
and everything else should work. But this workaround seems to me somehow dirty.
Can anybody advise me the correct way, how to solve this task? What is the best architecture for this? Is there any other way I am not seeing?
For your reference, I am also providing a snippet from the basic class, that is dealing with one message. The extension in whatever form should do basically the same, only with my own types.
public async Task NotificationOnAsync(NotificationSwitch Payload)
{
await PublishToBroker(String.Format("hermes/feedback/sound/toggleOn"), Payload.ToJSON());
}
private EventHandler<NotificationSwitchEventArgs> _notificationTurnedOn;
private object _notificationTurnedOnLock = new object();
public event EventHandler<NotificationSwitchEventArgs> NotificationTurnedOn
{
add
{
lock (_notificationTurnedOnLock)
{
_notificationTurnedOn += value;
SubscribeTopic("hermes/feedback/sound/toggleOn");
}
}
remove
{
lock (_notificationTurnedOnLock)
{
_notificationTurnedOn -= value;
if (_notificationTurnedOn is null) UnsubscribeTopic("hermes/feedback/sound/toggleOn");
}
}
}
protected virtual void OnNotificationTurnedOn(NotificationSwitchEventArgs e)
{
_notificationTurnedOn?.Invoke(this, e);
}
Thanks.
Jiri

If using DI + MEF, what is a good method to pass events between classes in the container?

I have a MEF container which contains hundreds of classes. What is a good way to pass messages between different classes?
I would prefer a solution that will work with any Dependency Injection (DI) container, including Unity, Castle Windsor, etc.
Note: This is a "share your knowledge, Q&A-style" entry.
Introducing the Event Publisher
This event publisher allows any class from the MEF container to send a message to any other class in the MEF container.
This code has been battle proven over a number of years, and has proven to be particularly useful when using WPF / MVVM.
It's a one-to-many subscription, so once the message is sent out, it is received by any listener that is observing messages of that custom type.
This example is for MEF, but it is also applicable to any other Dependency Injection (DI) container such as Unity, Castle Windsor, etc. If you convert EventPublisher to a singleton, you can use it with normal C# (i.e. not using a DI container). Let me know if you want me to post the code.
This code is nothing new: there are hundreds of other implementations of event publishers in the open source community, e.g. in MVVM Light. However, this example uses such a small amount of code that it's possible to see how it works under the hood, by single stepping in the debugger.
C# Usage
Add the boiler plate code to your project (see below).
Create your custom event type. This can be a class, a struct, or even an enum, e.g.:
public enum NavigationType
{
Unknown = 0,
MyOption1,
MyOption2
}
... then, I can import the eventPublisher into any class, like so:
[ImportingConstructor]
public BrokerOrderSearchResultViewModel(
IEventPublisher<NavigationType> eventPublisher,
)
{
_eventPublisher = eventPublisher;
...
... in the constructor, I can then subscribe to events of type NavigationType:
_eventPublisher.GetEvent<NavigationType>().Subscribe(o =>
{
Console.Write(o);
});
... and anywhere else, I can push events out, which will be received in the subscription:
_eventPublisher.Publish(NavigationType.MyOption1);
C# Boiler plate code
Add the Reactive Extensions (RX) NuGet package to your project.
Create this interface:
public interface IEventPublisher
{
IObservable<TEvent> GetEvent<TEvent>();
void Publish<TEvent>(TEvent sampleEvent);
}
public interface IEventPublisher<in T>
{
IObservable<TEvent> GetEvent<TEvent>() where TEvent : T;
void Publish<TEvent>(TEvent sampleEvent) where TEvent : T;
}
... with this implementation:
// NOTE: This class must be a singleton (there should only ever
// be one copy; this happens automatically in any dependency injection
// container). This class is the central dictionary that routes events
// of any incoming type, to all listeners for that same type.
[Export(typeof (IEventPublisher))]
public class EventPublisher : IEventPublisher
{
private readonly ConcurrentDictionary<Type, object> _subjects;
public EventPublisher()
{
_subjects = new ConcurrentDictionary<Type, object>();
}
public IObservable<TEvent> GetEvent<TEvent>()
{
return (ISubject<TEvent>)_subjects.GetOrAdd(typeof(TEvent), t => new Subject<TEvent>());
}
public void Publish<TEvent>(TEvent sampleEvent)
{
object subject;
if (_subjects.TryGetValue(typeof (TEvent), out subject))
{
((ISubject<TEvent>)subject).OnNext(sampleEvent);
}
// Could add a lock here to make it thread safe, but in practice,
// the Dependency Injection container sets everything up once on
// startup and it doesn't change from that point on, so it just
// works.
}
}
// NOTE: There can be many copies of this class, one for
// each type of message. This happens automatically in any
// dependency injection container because its a <T> class.
[Export(typeof (IEventPublisher<>))]
public class EventPublisher<T> : IEventPublisher<T>
{
private readonly IEventPublisher _eventPublisher;
[ImportingConstructor]
public EventPublisher(IEventPublisher eventPublisher)
{
_eventPublisher = eventPublisher;
}
public IObservable<TEvent> GetEvent<TEvent>() where TEvent : T
{
return _eventPublisher.GetEvent<TEvent>();
}
public void Publish<TEvent>(TEvent sampleEvent) where TEvent : T
{
_eventPublisher.Publish(sampleEvent);
}
}
Discussion
This code shows how simple it is to send an event from any class to any other class.
As shown, you need to create a new custom type in order to send a message. The type can be an enum, a struct, or a class. If the type is a class or a struct, it can contain any number of properties. If a message is sent out using a specific custom type, all subscribers listening to messages of that type will receive it. You can create many custom types, one for each flavour of event you need to communicate with.
Behind the scenes, all the code is doing is keeping a dictionary of your custom types. On a send, it looks up the appropriate subscribers in the dictionary, then sends the message using Reactive Extensions (RX). All subscribers listening to that type will then receive the message.
Sometimes, if there are too many events flying everywhere, it's difficult to see which classes are communicating with which other classes. In this case, it's simple: you can use "Find in Files" to find all classes that contain the string IEventPublisher<NavigationType>, which ends up listing all of the classes that are either sending or listening to an event of our custom type NavigationType.
Beware: this code is not a silver bullet. It is a bad code smell to rely on events too much, as the class hierarchy should be composed in such a way that classes should not be dependent on their parents. For more information, study the SOLID principles, in particular, the LSP. However, sometimes use of events are unavoidable, as we have no choice but to cross the class hierarchy.
Future Enhancements
Currently, this Event Publisher does not implement IDisposable. It should.
Use EventAggregator if you're not looking to do something overly elaborate.
http://blogs.msdn.com/b/gblock/archive/2009/02/23/event-aggregation-with-mef-with-and-without-eventaggregator.aspx
And a way to bring this into your project the MEFfy way:
https://msdn.microsoft.com/en-us/library/microsoft.practices.prism.mefextensions.events.mefeventaggregator(v=pandp.50).aspx
You could also write your own EventAggregator patter (per M. Fowler), but then you would have to take into consideration cleanly removing subscribed handlers, which will most likely lead you into the land of weak references and the horrors (or not) that lie there.

NServiceBus, Subscribe by interface when there are multiple interfaces

With NServiceBus you can subscribe by interface, eg:
public class MyEvent: ISomeInterface {}
public class Handler: IHandleMessages<ISomeInterface>{...}
This all seems to work happily, however when you have multiple interfaces eg:
public class MyEvent: ISomeInterface, ISomeOtherInterface {}
public class Handler: IHandleMessages<ISomeInterface>{/*Works fine*/}
public class Handler: IHandleMessages<ISomeOtherInterface>{/*Doesnt work*/}
When using pub/sub the message is correctly subscribed to in either case, but when the message is actually published the receiving service errors with:
No handlers could be found for message type: ISomeInterface
It appears to only work if the interface you are handling is the first on the sent message class. If I swap the order of interfaces on the actual event implementation around the second handler works fine but the first errors with a similar message (ie order of interfaces is whats causing the issue)
Is there some way to handle messages by interface no matter what order the interfaces were in when the message was constructed?
I've tried this with the handler using NSB 3 and NSB 4 both produce the same result.
EDIT:
As requested heres a more detailed snippet of the subscriber config I am using. I've also put together a minimal repro pub/sub app to demonstrate the issue I'm having (on github here).
Configure.Features.Disable<NServiceBus.Features.TimeoutManager>().Disable<NServiceBus.Features.SecondLevelRetries>();
Configure.With()
.DefineEndpointName("nsbinterfaces.subscriber")
.DefiningEventsAs(t => t.Namespace != null && t.Namespace.Contains(".Events"))
//.NinjectBuilder(kernel)
.DefaultBuilder()
.UseTransport<Msmq>()
.PurgeOnStartup(false)
.MsmqSubscriptionStorage("nsbinterfaces.subscriber")
.UnicastBus()
.LoadMessageHandlers()
.ImpersonateSender(false)
.CreateBus()
.Start(
() => Configure.Instance.ForInstallationOn<NServiceBus.Installation.Environments.Windows>().Install());
After looking at the repro, I think I know what's going on.
Your Publisher knows about it's own event (MyEvent) and two interfaces that it implements. The two interfaces are in an assembly that is shared.
Your subscriber knows nothing about MyEvent, so it doesn't know that it implements both interfaces. It's either an ISomeInterface or an ISomeOtherInterface, so it deserializes it to one of those types.
Since the order of the interface seems to dictate what type of message it is received as, I would guess that NSB will deserialize the message to the first type it sees that it knows about (per process).
<?xml version="1.0"?>
<Messages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://tempuri.net/NsbInterfaces.Publisher.Events"
xmlns:baseType="NsbInterfaces.Events.ISomeInterface"
xmlns:baseType1="NsbInterfaces.Events.ISomeOtherInterface">
<MyEvent></MyEvent>
</Messages>
You need to move you interface implementation to the shared assembly (NsbInterfaces.Events)
Added a pull request to you repo
HTH
I asked this question in the NSB forums and its been converted to an issue, which looks like it should be resolved in v5 of the software. (https://github.com/Particular/NServiceBus/issues/2301)
Until its fixed I think there's 2 options:
Send it as 2 separate messages
Put the implementation into the published library (Thanks #seanfarmar)

AoP support in NServiceBus?

Ties back to my old question here:
But I really want to intercept messages AND have an instance of the handler and be able to influence the whether the message should go to the handler at all. Basically an "around advice".
Now the most traditional way of implementing something like this is via dynamic inheritance of the target object and overriding the virtual methods. The thing that I could not tell due to lack of documentation whether, NServiceBus creates or builds up its message handler instances. If it builds up, then it can't dynamically inherit, so most AoP framework is probably out of the question, otherwise most popular DI container should do the trick.
However testing with Saga handers it seems like NServiceBus builds up rather than creates new due to the requirement for a default constructor, which points to NServiceBus manually activating the class.
Yes I realize I can use good ole' OOP to solve the same problem, but I usually prefer AoP for better (less) coupling.
If all you want to do is influence if a message should go to a handler or not, then NServiceBus provides a solution for that => DoNotContinueDispatchingCurrentMessageToHandlers()
You can create a generic handler and set it up to fire before any other handlers.
public class SomeHandler: IHandleMessages<object>, ISpecifyMessageHandlerOrdering
{
public IBus Bus {get;set;}
public void Handle(object message)
{
Bus.DoNotContinueDispatchingCurrentMessageToHandlers();
}
public void SpecifyOrder(Order order)
{
order.SpecifyFirst<SomeHandler>();
}
}
For more details see this answer
Alternatively, this can be plugged in as a mutator
class StopThePipelineMutator: IMutateIncomingTransportMessages,INeedInitialization
{
public IBus Bus { get; set; }
public void MutateIncoming(TransportMessage transportMessage)
{
Bus.DoNotContinueDispatchingCurrentMessageToHandlers();
}
public void Init()
{
Configure.Component<StopThePipelineMutator>(DependencyLifecycle.InstancePerCall);
}
}
Old post, but someone looking for a way to get AOP with NServiceBus, here's a different way of doing it:
https://github.com/MeTitus/NServiceBus/commit/278b6bf4e3daba2fbdfc5295b8718609946d653d
The other way is to user PostSharp.

NHibernate Multiple Event Listeners

Is it possible to register multiple event listeners?
We currently register event listeners using .ExposeConfiguration(AddSoftDelete) in which AddSoftDelete is a class registering the listener;
private static void AddSoftDelete(Configuration config)
{
config.SetListener(ListenerType.Delete, new SoftDeleteListener());
}
We have found that we cannot register multiple event listeners of the same type, i.e. we cannot register more than one listener for "ListenerType.Delete".
Is it possible to register new listeners without overriding any existing ones?
Solved...
Have managed to register multiple listeners using the following code;
config.EventListeners.PreUpdateEventListeners = new IPreUpdateEventListener[]
{
new Listener1(),
new Listener2()
};
Repeat for each ListenerType.
The listeners are not actually listeners, they are implementors. There could only be one implementation of an "event".
You could implement a listener where you could plug in several implementations. For instance an implementation for different entity types. You could pass the "event" to each implementation until one of them handles it (eg. when the ISoftDeletable interface is implemented, the SoftDeleteImplementor is handling it). You need to care about competing implementors (more the one could be handling it, the order matters in which you call them).
Why is there a need to register more than one ListenerType.Delete?
If you've got multiple event listeners on one type, there will be some performance issues on your application. If you want to handle different entities with this listener, so do it in your SoftDeleteListener class.
I do something similar in my code. There should be an AppendListeners(ListenerType type, object[] listeners) method on the NHibernate.Cfg.Configuration object.
There's also a SetListeners method which I assume replaces the listener list instead of adding on to it.

Categories