NServiceBus, Subscribe by interface when there are multiple interfaces - c#

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)

Related

How does __TransparentProxy work?

When using WCF, we can define a service contract:
[ServiceContract]
public interface IMyService
{
[OperationContract]
int MyOperation(int x);
}
Assume I open a servicehost at www.example.com/MyService, then one way to use this service from my client is
IMyService service =
new ChannelFactory<IMyService>(new BasicHttpBinding(),
new EndpointAddress("www.example.com/MyService")).CreateChannel();
int result = service.MyOperation(10);
So somehow, service implements IMyService, although that was never done explicitly. If I debug these lines, I can see that service is an instance of __TransparentProxy. As you can see from the source code, the comments in that class say
Transparent proxy magically creates a message that represents a call on it and delegates to the Real proxy to do the real remoting work.
To me this is indeed 'magic', but I guess there must be a logical explanation.
The pattern here can be very useful. What I would like is some class like Magic below (the syntax is incorrect, I know, otherwise I wouldn't need to ask). For the sake of argument, let's say I want this class to print the name of the method called.
public class Magic<T> : T {
// don't know what to do here
}
Such that I would be able to call
IMyService service = new Magic<IMyService>();
service.MyOperation(10);
And this would print:
MyOperation
Is something like this possible? (It should be, since __TransparentProxy does something similar.) And if so, how would this work?
There are a few articles on Codeplex that try to do something similar to what WCF does under the covers:
http://www.codeproject.com/Articles/43598/Emit-Proxy
http://www.codeproject.com/Articles/5511/Dynamic-Proxy-Creation-Using-C-Emit
The System.Reflection.Emit namespace is the underlying key, which can be used to dynamically create .NET assemblies and types in code.
Any one else running across this answer might want to look at Aspect Oriented Programming (AOP) in general
And possibly PostSharp specifically: https://www.postsharp.net/aop.net

Flexible Logging interface design in C#

I want to write my own Logging classes (in C#) which implement a standard interface, which I can call from any part of the code.
My idea is to have multiple Log classes implement the Logger interface, each for its specific log destination, for example, a FileLogger will implement logging to a file, a TextBox logger will implement logging into a Multi Line TextBox in a Form, a DBLogger will implement logging to a database table, etc.
Further, each logger class can have a nested logger or chained logger classes, so that a single call to Log() method from the application code can log the message in multiple destinations; example log to a file and a textbox on Form in a single call.
The difficulty I am facing is this:
Usually I log to a running log file (which will contain all log messages required for debugging), a review log file (which will contain only log messages to be reviewed by the user, or which require user action), a Multi Line textbox on screen (which will replicate all log messages to give a progress indication to the user), and another Multi Line textbox (which will log only messages required for user to review).
When I call logger.Log(message), some messages may not apply to a particular log destination. For example, some message may be intended to be logged only in a running log file or progress textbox, but not in the user review textbox, and vice versa.
Since the loggers will be chained so that a single function call can log into all required destinations, how can a particular logger identify that the log message is not intended for it and hence ignore the log message?
My sample log interface is:
public interface Logger
{
public void Log(string msg);
public void Log(string msgType, string msg);
public void InitLogSession();
public void EndLogSession();
public void AddLogger(Logger chainedLogger);
public void RemoveLogger(Logger chainedLogger);
}
public class FileLogger : Logger
{
//implement methods
}
public class TextBoxLogger : Logger
{
//implement methods
}
public class DBLogger : Logger
{
//implement methods
}
EDIT 1:
To be more precise, there could be 4 loggers: 2 file loggers and 2 textbox loggers. A particular message is suppose meant for 1 of the textbox loggers, and 1 of the file loggers; how should my design handle this?
EDIT 2:
Please do not suggest existing logging frameworks. I just want to write it on my own !
EDIT 3:
Ok. I have a design. Please give your feedback and probably fill the gaps.
The revised interface:
public interface Logger
{
public void Log(string msg);
public void Log(string msgType, string msg);
public void Log(int loggerIds, string msg);
public void Log(int loggerIds, string msgType, string msg);
public void InitLogSession();
public void EndLogSession();
public int getLoggerId();
}
public enum LoggerType
{
File,
TextBox
};
public class LoggerFactory
{
public Logger getLogger(LoggerType loggerType)
{
}
}
The LoggerFactory class will be the sole way to instantiate a logger. This class will assign a unique id to each instance of a logger. This unique id will be a power of 2. Example, 1st logger will get id 1, 2nd will get id 2, 3rd will get 4, and 4th will get 8, and so on.
The returned logger object can be typecast to specific class, and further values like filePath, textbox, etc. can be set by the caller, or else I can have multiple methods in LoggerFactory: one for each type of logger, which will accept specific parameters.
So, suppose we have 4 loggers with ids 1,2,4,8.
A particular message which has to be processed by the 1st and 3rd logger (i.e. logger ids 1 and 4) has to be logged using the function:
public void Log(int loggerIds, string msg);
The value to be passed to loggerIds should be "0101". Each logger will check whether its logger id bit is ON. If yes, only then it will log the message.
Now in the function signatures, I have mentioned int type, but which is the specific optimised type for performing bit manipuations and comparisons?
In this approach, there can probably be a limit on the max no. of loggers, but that is fine with me. Please give your feedback.
Note: Currently I am still on .NET 2.0. If possible, suggest solution within .NET 2.0, else fine, I can move to higher versions.
CONS of this design: Each class which needs to log, needs to know about all the available loggers instantiated by the application, and accordingly set up the bit pattern. Any ideas how to have a loosely coupled design?
Why don't you look at (or indeed use) an existing logging framework such as log4net or NLog.
They have the concept of a log level (e.g. trace, info, error etc) as well as being able to filter by the name of the log (which is normally the fully qualified type name which invoked the logging call). You can then map these to one or more 'targets'.
"Please do not suggest existing logging frameworks. I just want to write it on my own !"
Accepted answer: Don't reinvent the wheel! Use this existing logging framework!
facepalm
The best answer, which is my answer, goes something like this.
Use interfaces if you want plug and play functionality. You can make it easily configurable. Here's the high level run down.
Use a config file to indicate what type of logger you want
which implements your logging interface
Use reflection to instantiate the type you pull from
your config file AT RUNTIME.
Pass in your logger interface you just made via constructor injection inside your classes.
You're not reinventing the wheel by designing by interface.
If you make your interface general enough, it is implementation non specific (ideally).
This means if log4net goes to crap, or is no longer supported, you don't have to RIP OUT AND MODIFY ALL YOUR CALLING CODE. This is like hard-wiring a lamp directly into your house to turn it on. For the love of god, please don't do that.
The interface defines the contract by which the components interact, not the implementation.
The only thing I can think of is, look at existing logging frameworks, find the common elements, and write your interface as the intersection of the common features. Obviously there are going to be features that you miss. It depends on how much flexibility you want. You can use Log4net, or the Microsoft Event Viewer logger, or both! No implementation details are re implemented. And it is a MUCH less coupled system than having everything in your code tied to one technology / framework.
As devdigital wrote, these Frameworks usually do this by providing designated methods for Logging like: Warn("..."), Fail("...")...
You could also look for the ILogger interface of the logging facility of the castle project. (maybe try to google the ILogger.cs sourcecode)
If you still adhere to your approach of chained loggers with common interface (for which you you would also have to implement a chaining mechanism) you would have to provide a kind of logging level to your Log() method. This may be just an integer or an enum as well.
Like this:
public interface Logger
{
public void Log(LogLevel level, string msg);
public void Log(LogLevel level, string msgType, string msg);
public void InitLogSession();
public void EndLogSession();
public void AddLogger(Logger chainedLogger);
public void RemoveLogger(Logger chainedLogger);
}
With an logging level enum like this:
public enum LogLevel
{
Info,
Warn,
Debug,
Error,
Fail
}
The loggers to use would then be selected within a chain of responsibility.
I wrote my own logger some time ago. To be honest it was not as good as those available for free and I realized that I was trying to re-invent a wheel that was already round!
I see that you want to write your own code but it might still be an idea to look at open source solutions and perhaps use them or modify them for your own specific needs
I now use TracerX: http://www.codeproject.com/Articles/23424/TracerX-Logger-and-Viewer-for-NET This is an open source project so it easy to modify the source code it you need to. The other loggers mentioned are also good of course.
EDIT
This is based on the accepted answer to my question here: How to pass status information to the GUI in a loosely coupled application So I claim no originality in this. Your log messages are simple at the moment I think
My suggested answer is that you use a message type that can process (e.g.) send itself to different loggers based on either some logic passed to it at run time or by using a factory to create different message types depending on run time conditions.
So
create an abstract message class or interface that has a process method.
create a number of message types inheriting from the abstract class or interface that represent the different types of logging you want to carry out. The process method could determine where to send them.
Consider using a factory to create the message type you need during runtime so you don't need to decide what types you will need in advance
When you generate a log message use the process message to route the message to the loggers you want it to go to
This seem like a good place to use extension methods.
Create your base class, then create the extension methods for it.
BaseLogger(LogMessage).toTextBoxLog().toFileLog().toDatabaseLog().
This way, you always call the BaseLogger and then only the extension methods where needed.
.NET now provides the ILogger interface which can be used with a variety of .NET or 3rd party logging tools through dependency injection.
Using this you can separate your logging functionality in code, from the concrete implementation in your architecture, and can later swap out loggers without significant modification to your business code.
https://learn.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger?view=dotnet-plat-ext-6.0
https://learn.microsoft.com/en-us/dotnet/core/extensions/logging?tabs=command-line

NServiceBus custom message handler type

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.

WCF - Generalizing Action String

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.

How do I configure a single component instance providing multiple services in Castle.Windsor?

I'd like to configure the Windsor container so that a single, singleton-style instance can provide two or more services through the container.
I've found that using the same type in multiple component declarations (XML-based config) will result in an instance of that type being created to provide each component's service interface, which is not the behaviour I desire.
For example:
interface IA { }
interface IB { }
class AB : IA, IB { ... }
I want the one instance of AB to provide both the IA and IB services.
The specific reason I want to do this is that my concrete DAO implementation extends multiple interfaces. On the flip side, I have several worker components which hold a reference to different interfaces. The concrete DAO instance respects this, but the constructors of these seperate worker components want the implementation of their seperate interfaces and I desire Castle.Windsor to pass the same object instance through to these worker containers via the respective service requests.
lol, I think that was clear as mud! :P
Does anyone understand what I mean, and has anyone got any ideas how I can acheive this through the XML configuration fo the components?
Have you checked out the answer to this question (especially the forum post link) that appears to be what you are looking for. Some of the examples are using the Transient lifecycle but I think it will work with Singleton also.
The main pay-off of the forum post is:
container.Register(Component.For<IEntityIndexController, ISnippetController>()
.ImplementedBy<SnippetController>()
.LifeStyle.Transient);
The solution is uses the fluent interface (and a recent trunk build) and it wasn't possible to configure in xml last I saw. However, it may be possible with a facility.
Good luck!
Have you tried using the Forward method:
container.Register(Component.For<IEntityIndexController>()
.ImplementedBy<SnippetController>()
.Forward (typeof(ISnippetController))
.LifeStyle.Transient);
From my experiments and from the documentation:
register the service types on behalf of this component
i think it shoud do the trick.
You can register an instance of an object (instead of an implementation) to be responsible for different implementations:
var ab = new AB();
container.Register( Component.For<IA>().Instance( ab) );
container.Register( Component.For<IB>().Instance( ab) );
I believe that should work. However, that requires in code configuration, for apparent reasons.
I was searching for the same answer, and this post is the farthest I could get with google. I found that using
Classes.FromThisAssembly().Where(t => t.FullName == "Namespace.Classname").WithServiceAllInterfaces()
Seems to do the trick for me.

Categories