C# method overloading and interfaces - c#
Scrumbling my head around basics.
I have a couple of (for the example let's say) message classes sharing a common base class. And I have an interface that accepts the base class as argument. So far I thought it would easily be possible to use method overloading to handle specific types of messages in seperated methods.
How could you get this following sample running:
using System;
namespace MethodOverloading
{
// for the example: we are sending messages
// which have a common base class
public class MessageBase
{
public readonly string Value;
public MessageBase() { Value = GetType().Name; }
}
// and there are a couple of concrete instances
public class Message1000 : MessageBase { }
public class Message2000 : MessageBase { }
public class Message3000 : MessageBase { }
public class Message4000 : MessageBase { }
public class Message5000 : MessageBase { }
// and of cource we have an interface receiving all messages but only with one method for the base defined
public interface IHandler
{
void ReceiveMessage(MessageBase msg);
}
// the handlers should do some method overloading so a overloaded method can be implemented for each supported message
// and the base message catches all unsupported messages (e.g. log: ey, missed an overload for this type)
// Handler 1 tries to overload the interface method
public class Handler1 : IHandler
{
public void ReceiveMessage(MessageBase msg) { Console.WriteLine($"Handler1.ReceiveMessage(MessageBase:{msg.Value})"); }
public void ReceiveMessage(Message1000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message1000:{msg.Value})"); }
public void ReceiveMessage(Message2000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message2000:{msg.Value})"); }
public void ReceiveMessage(Message3000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message3000:{msg.Value})"); }
public void ReceiveMessage(Message4000 msg) { Console.WriteLine($"Handler1.ReceiveMessage(Message4000:{msg.Value})"); }
// intentionally no overload for Message5000
}
// Handler 2 provides one interface method and has protected overloads...
public class Handler2 : IHandler
{
public void ReceiveMessage(MessageBase msg)
{
Console.Write($"Handler2.ReceiveMessage(MessageBase:{msg.Value}) > ");
HandleMessage(msg);
}
protected void HandleMessage(MessageBase msg) { Console.WriteLine($"Handler2.HandleMessage(MessageBase:{msg.Value})"); }
protected void HandleMessage(Message1000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message1000:{msg.Value})"); }
protected void HandleMessage(Message2000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message2000:{msg.Value})"); }
protected void HandleMessage(Message3000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message3000:{msg.Value})"); }
protected void HandleMessage(Message4000 msg) { Console.WriteLine($"Handler2.HandleMessage(Message4000:{msg.Value})"); }
// intentionally no overload for Message5000
}
class Program
{
static void Main(string[] args)
{
// so lets give it a try ....
Console.WriteLine("Testing method overloads");
MessageBase msgBase = new MessageBase();
Message1000 msg1000 = new Message1000();
Message2000 msg2000 = new Message2000();
Message3000 msg3000 = new Message3000();
Message4000 msg4000 = new Message4000();
Message5000 msg5000 = new Message5000();
Console.WriteLine("Handler1:");
Handler1 handler1 = new Handler1();
handler1.ReceiveMessage(msgBase);
handler1.ReceiveMessage(msg1000);
handler1.ReceiveMessage(msg2000);
handler1.ReceiveMessage(msg3000);
handler1.ReceiveMessage(msg4000);
handler1.ReceiveMessage(msg5000);
Console.WriteLine("iHandler1:");
IHandler ihandler1 = new Handler1();
ihandler1.ReceiveMessage(msgBase);
ihandler1.ReceiveMessage(msg1000);
ihandler1.ReceiveMessage(msg2000);
ihandler1.ReceiveMessage(msg3000);
ihandler1.ReceiveMessage(msg4000);
ihandler1.ReceiveMessage(msg5000);
Console.WriteLine("Handler2:");
Handler2 handler2 = new Handler2();
handler2.ReceiveMessage(msgBase);
handler2.ReceiveMessage(msg1000);
handler2.ReceiveMessage(msg2000);
handler2.ReceiveMessage(msg3000);
handler2.ReceiveMessage(msg4000);
handler2.ReceiveMessage(msg5000);
Console.WriteLine("iHandler2:");
IHandler ihandler2 = new Handler2();
ihandler2.ReceiveMessage(msgBase);
ihandler2.ReceiveMessage(msg1000);
ihandler2.ReceiveMessage(msg2000);
ihandler2.ReceiveMessage(msg3000);
ihandler2.ReceiveMessage(msg4000);
ihandler2.ReceiveMessage(msg5000);
Console.WriteLine("press any key to exit");
Console.ReadLine();
}
}
}
The output actually is:
Testing method overloads
Handler1:
Handler1.ReceiveMessage(MessageBase:MessageBase)
Handler1.ReceiveMessage(Message1000:Message1000)
Handler1.ReceiveMessage(Message2000:Message2000)
Handler1.ReceiveMessage(Message3000:Message3000)
Handler1.ReceiveMessage(Message4000:Message4000)
Handler1.ReceiveMessage(MessageBase:Message5000)
iHandler1:
Handler1.ReceiveMessage(MessageBase:MessageBase)
Handler1.ReceiveMessage(MessageBase:Message1000)
Handler1.ReceiveMessage(MessageBase:Message2000)
Handler1.ReceiveMessage(MessageBase:Message3000)
Handler1.ReceiveMessage(MessageBase:Message4000)
Handler1.ReceiveMessage(MessageBase:Message5000)
Handler2:
Handler2.ReceiveMessage(MessageBase:MessageBase) > Handler2.HandleMessage(MessageBase:MessageBase)
Handler2.ReceiveMessage(MessageBase:Message1000) > Handler2.HandleMessage(MessageBase:Message1000)
Handler2.ReceiveMessage(MessageBase:Message2000) > Handler2.HandleMessage(MessageBase:Message2000)
Handler2.ReceiveMessage(MessageBase:Message3000) > Handler2.HandleMessage(MessageBase:Message3000)
Handler2.ReceiveMessage(MessageBase:Message4000) > Handler2.HandleMessage(MessageBase:Message4000)
Handler2.ReceiveMessage(MessageBase:Message5000) > Handler2.HandleMessage(MessageBase:Message5000)
iHandler2:
Handler2.ReceiveMessage(MessageBase:MessageBase) > Handler2.HandleMessage(MessageBase:MessageBase)
Handler2.ReceiveMessage(MessageBase:Message1000) > Handler2.HandleMessage(MessageBase:Message1000)
Handler2.ReceiveMessage(MessageBase:Message2000) > Handler2.HandleMessage(MessageBase:Message2000)
Handler2.ReceiveMessage(MessageBase:Message3000) > Handler2.HandleMessage(MessageBase:Message3000)
Handler2.ReceiveMessage(MessageBase:Message4000) > Handler2.HandleMessage(MessageBase:Message4000)
Handler2.ReceiveMessage(MessageBase:Message5000) > Handler2.HandleMessage(MessageBase:Message5000)
press any key to exit
Handler 1 actually works when called directly. Unfortunatly not out of the box when called as interface.
Though I thought at least Handler2 with the protected overloads would do the trick....
What I am actually trying to get rid of is the switch statement with castings in Handler3 (because that extra step could easily be missed and it would be great to do that magic in a base class unaccessible for the developers):
public class Handler3 : IHandler
{
public void ReceiveMessage(MessageBase msg)
{
Console.Write($"Handler3.ReceiveMessage(MessageBase:{msg.Value}) > ");
switch (msg)
{
case Message1000 msg1000: HandleMessage(msg1000); break;
case Message2000 msg2000: HandleMessage(msg2000); break;
case Message3000 msg3000: HandleMessage(msg3000); break;
case Message4000 msg4000: HandleMessage(msg4000); break;
default: Console.WriteLine("dropped because not supported: " + msg.Value); break; // for the msg5000
}
}
//protected void HandleMessage(MessageBase msg) { Console.WriteLine($"Handler3.HandleMessage(MessageBase:{msg.Value})"); }
protected void HandleMessage(Message1000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message1000:{msg.Value})"); }
protected void HandleMessage(Message2000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message2000:{msg.Value})"); }
protected void HandleMessage(Message3000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message3000:{msg.Value})"); }
protected void HandleMessage(Message4000 msg) { Console.WriteLine($"Handler3.HandleMessage(Message4000:{msg.Value})"); }
// intentionally no overload for Message5000
}
Which would actually works as shown by the output:
Handler3:
Handler3.ReceiveMessage(MessageBase:MessageBase) > dropped because not supported: MessageBase
Handler3.ReceiveMessage(MessageBase:Message1000) > Handler3.HandleMessage(Message1000:Message1000)
Handler3.ReceiveMessage(MessageBase:Message2000) > Handler3.HandleMessage(Message2000:Message2000)
Handler3.ReceiveMessage(MessageBase:Message3000) > Handler3.HandleMessage(Message3000:Message3000)
Handler3.ReceiveMessage(MessageBase:Message4000) > Handler3.HandleMessage(Message4000:Message4000)
Handler3.ReceiveMessage(MessageBase:Message5000) > dropped because not supported: Message5000
But it is a benefit that the compiler complains and prevents builds if you miss an method overload using that variant.
Well, yes. Remember that overload resolution is done at compile-time using the compile-time types of your variables, and not at runtime. The runtime types are irrelevant.
IHandler only has the overload void ReceiveMessage(MessageBase msg). So when you call IHandler.ReceiveMessage(msg), whatever subclass msg happens to be, it has to call IHandler.ReceiveMessage(MessageBase msg), because that's the only method which IHandler defines.
It doesn't matter that Handler1 defines other other methods which aren't in IHandler: your Main method is working with an instance of IHandler, and so void ReceiveMessage(MessageBase msg) is the only overload it can see.
In Handler2.ReceiveMessage(MessageBase msg), msg has the compile-time type MessageBase. You can see it in the method signature. So when you call HandleMessage(msg), msg is a MessageBase, so the compiler has to pick the HandleMessage(MessageBase msg) overload.
One possible way to achieve what you're after is to use the visitor pattern. This lets you take a variable with a compile-time type of MessageBase, and find out what its run-time type is by asking it to call a specific method on you. Something like:
public interface IMessageVisitor
{
void Accept(Message1000 msg);
void Accept(Message2000 msg);
}
// for the example: we are sending messages
// which have a common base class
public abstract class MessageBase
{
public readonly string Value;
public MessageBase() { Value = GetType().Name; }
public abstract void Visit(IMessageVisitor visitor);
}
// and there are a couple of concrete instances
public class Message1000 : MessageBase
{
public override void Visit(IMessageVisitor visitor) => visitor.Accept(this);
}
public class Message2000 : MessageBase
{
public override void Visit(IMessageVisitor visitor) => visitor.Accept(this);
}
public interface IHandler
{
void ReceiveMessage(MessageBase msg);
}
public class Handler1 : IHandler, IMessageVisitor
{
public void ReceiveMessage(MessageBase msg) => msg.Visit(this);
public void Accept(Message1000 msg) => Console.WriteLine("Message1000");
public void Accept(Message2000 msg) => Console.WriteLine("Message2000");
}
See it on dotnetfiddle.net.
Methods are resolved based on type of the object, not the type of the parameter. I.e. you will call Handler1.ReceiveMessage or Handler2.ReceiveMessage based on the type of the handler object, not the message object. This is technically known as "single dispatch"
What you want is "multiple dispatch", i.e. you want the method to be resolved based on two different objects.
One way to do this would be to change your interface to an abstract base class and use pattern matching to map the type to the correct method
public abstract class HandlerBase
{
protected abstract void ReceiveMessage(Message1000 msg);
protected abstract void ReceiveMessage(Message2000 msg);
// etc
void ReceiveMessage(MessageBase msg){
switch(msg){
case Message1000 msg1000:
ReceiveMessage(msg1000);
break;
case Message2000 msg2000:
ReceiveMessage(msg2000);
break;
// etc
}
}
}
Another alternative is the visitor pattern:
public abstract class MessageBase
{
public readonly string Value;
public MessageBase() { Value = GetType().Name; }
public abstract void Visit(IVisitor visitor);
}
public class Message1000
{
public override void Visit(IVisitor visitor) => visitor.ReceiveMessage(this);
}
public interface IVisitor{
void ReceiveMessage(Message1000 msg);
void ReceiveMessage(Message2000 msg);
// etc...
}
The visitor pattern will force you to implement all the needed methods, a new message type must have an Accept method, and to implement this you need a new ReceiveMessage overload, and that has to be implemented by all the visitors/handlers. If this is a benefit or not is up to you.
A third alternative is to use "dynamic", but I would not recommend it since it will disable all type checking.
Related
Castle windsor typed factory - resolving generic service using runtime type as parameter
I have a typed factory with this method: IRepository<T> Get<T>() where T : class and the following component type selector: public class RepositoryComponentSelector : DefaultTypedFactoryComponentSelector { protected override string GetComponentName(MethodInfo method, object[] arguments) { return ComponentNames.Repository; } protected override Type GetComponentType(MethodInfo method, object[] arguments) { return typeof(Repository<>).MakeGenericType(method.GetGenericArguments()[0]); } } What I would like however, is to have a factory implementation that returns a Repository, but by only having to specify a parameter of type Type, not a compile time type parameter. Example (not valid code) - I want the T to be the Type provided IRepository<T> Get(Type type); I am aware that this does not compile because the method itself has to be generic, but I don't know the parameter beforehand. What I am trying to achieve is to simplify this pattern: if (documentType == SomeEnum.x) { this.RepositoryFactory.Get<X>().Update(document as X); } else if (documentType == SomeEnum.y) { this.RepositoryFactory.Get<Y>().Update(document as Y); } else if (documentType == SomeEnum.z) { this.RepositoryFactory.Get<Z>().Update(document as Z); } by resolving the factory based on the enum (or an extension to that enum returning Type). Is there a way to achieve this with Castle Windsor, or any other approaches I could take?
I believe this is more about polymorphism and general dispatching problem, rather than hooking this into container. You can use double dispatch approach: public void Save(DocumentBase document) { var dispatcher = new DocumentDispatcher(); document.Accept(dispatcher); } public abstract class DocumentBase { public abstract void Accept(IDocumentDispatcher dispatcher); } public class DocumentA : DocumentBase { public override void Accept(IDocumentDispatcher dispatcher) { dispatcher.Dispatch(this); } } public class DocumentB : DocumentBase { public override void Accept(IDocumentDispatcher dispatcher) { dispatcher.Dispatch(this); } } public interface IDocumentDispatcher { void Dispatch(DocumentA document); void Dispatch(DocumentB document); } public class DocumentDispatcher : IDocumentDispatcher { public void Dispatch(DocumentA document) { this.RepositoryFactory.Get<DocumentA>().Update(document); } public void Dispatch(DocumentB document) { this.RepositoryFactory.Get<DocumentB>().Update(document); } } Alternatively you can use dynamic dispatch: public void Save(DocumentBase document) { var dispatcher = new DocumentDispatcher(); dispatcher.Dispatch((dynamic)document); } public class DocumentDispatcher : IDocumentDispatcher { public void Dispatch<T>(T document) { this.RepositoryFactory.Get<T>().Update(document); } } Or even dictionary dispatch: public void Save(DocumentBase document) { var actions = new Dictionary<Type, Action<DocumentBase>> { { typeof(DocumentA), d => this.RepositoryFactory.Get<DocumentA>().Update((DocumentA)d) }, { typeof(DocumentB), d => this.RepositoryFactory.Get<DocumentB>().Update((DocumentB)d) }, }; actions[typeof(DocumentBase)](document); } I prefer first solution as it is only one type safe solution.
Pass more-derived type (via 'this') in less-derived method to overloaded method
Simple hierarchy, 3 levels and with a shared/single dependency to a class with overloaded methods that differ only by type signature: When viewed in a debugger, the type of 'this' in Derived.Bar is the instantiated/concrete Double-Derived. The below works as expected ONLY because of the (dynamic) cast. Remove it and you'll see that the overload resolution uses the calling class rather than the concrete class. Curious if there's a 'purer' way of it working as expected without the performance hit of DLR (or some other reflection-based alternative): public class PolymorphicConsumer { public void Foo(Base caller) { Console.WriteLine("Its all about the base."); } public void Foo(Derived caller) { Console.WriteLine("Its all about the Derived."); } public void Foo(DoubleDerived caller) { Console.WriteLine("Its all about the Double-Derived."); } } public abstract class Base { protected PolymorphicConsumer _dep; public Base (PolymorphicConsumer dep) { _dep = dep; } public virtual void Bar() { // No impl. } } public class Derived : Base { public Derived(PolymorphicConsumer dep):base(dep) { } public override void Bar() { _dep.Foo((dynamic)this); } } public class DoubleDerived : Derived { public DoubleDerived(PolymorphicConsumer dep):base(dep) { } } class Program { static void Main(string[] args) { var dd = new DoubleDerived(new PolymorphicConsumer()); dd.Bar(); Console.ReadKey(); } }
when i want to have a base Interface and implement from it the call is ambiguous between the following methods or properties
I know that the call is ambiguous between the following methods or properties and I know the meaning of this error but You see this implementation . I saw examples of each class being created on the interface, but I use the IOC. interface IOne { void Save(string text); } interface ITwo { void Save(string two); } class One : IOne { public void Save(string text) { throw new NotImplementedException(); } } class Two : ITwo { public void Save(string two) { throw new NotImplementedException(); } } interface IBase : IOne, ITwo { } class Base : IBase { void ITwo.Save(string two) { throw new NotImplementedException(); } void IOne.Save(string text) { throw new NotImplementedException(); } } class RunClass { private readonly IBase _base; public RunClass(IBase #base) { this._base = #base; } public void SaveMethod(string t = "Test") { _base.Save(t); } } when i call this line _base.Save(t); i get this error the call is ambiguous between the following methods or properties. Is there a way to implement this type of implementation?
At first you need to know which of the two Save methods you want to call. Then you can implement it by casting explicitly: public void SaveMethod(string t = "Test") { ((IOne)_base).Save(t); // or ((ITwo)_base).Save(t); }
Generic message handlers
I want to create a generic mechanism for handling messages in C#. I have a need for this in my small application, so I don't want to use full blown message bus. My requirements are quite simple: I want to have a couple of classes for messages i.e. Message1, Message2. They can inherit from one base class, that's not a problem, but if they don't I don't care. Currently they do inherit from Message. be able to get handler for each and every message class. i.e. if I send Message1, then Message1Handler class should be instantiated. Handlers have to implement IMessageHandler<T> where T is the message class. IMessageHandler is defined as follows: interface IMessageHandler<T> { void Execute(T message); } I wrote a simple "Resolver" class: public static class HandlerRegistry { private static readonly Dictionary<string, Type> _handlers = new Dictionary<string, Type>(); public static void Register<T, T2>() where T2: IMessageHandler<T> { _handlers.Add(typeof(T).FullName, typeof(T2)); } public static IMessageHandler<T> Resolve<T>(T parameters) { var type = _handlers[parameters.GetType().FullName]; return (IMessageHandler<T>) Activator.CreateInstance(type); } } In this implementation everything is OK, but one part - the cast to IMessageHandler. When I'm trying to use this with a collection of messages this is what happens: the compiler doesn't know at compile time what actual messages are going to be in the collection - it just assumes that they are all subclasses of Message, so it's trying to cast IMessageHandler<ConcreteMessage> to IMessageHandler<Message> and obviously I'm getting an exception with invalid cast. In this case probably contravariance would help, but I'm not able to declare the parameter as out because I have the message in the Execute method parameters. Does anyone know an elegant solution to this problem? I know I can make it "more runtime" - instead of using generics just declare void Execute(Message m) and in each and every handler start with trying to cast to the type that I'm expecting, but as someone said somewhere - each and every cast that you write undermines the whole point of using a type system.
Option 1 If you do not care using reflection. You can add a Execute method to your HandlerRegistry instead of returning the handler back to the caller: public static void Execute<T>(T parameters) { var type = _handlers[parameters.GetType().FullName]; var handler = Activator.CreateInstance(type); type.GetMethod("Execute", new[] { parameters.GetType() }) .Invoke(handler, new object[] { parameters }); } Option 2 If you do not care that one message handler can only subscribe to one message. We can take advantage of the Explicit Interface Implementation feature of C#: // NOTE: This interface is not generic public interface IMessageHandler { void Execute(object message); } public abstract class MessageHandler<T> : IMessageHandler { public abstract void Execute(T message); // NOTE: Here we explicitly implement the IMessageHandler void IMessageHandler.Execute(object message) { Execute((T)message); } } Now your resolve method can change to: public static IMessageHandler Resolve<T>(T parameters) { var type = _handlers[parameters.GetType().FullName]; return (IMessageHandler)Activator.CreateInstance(type); } By the way, personally I would prefer to pass in a Type instead of the message instance. Then make your handlers inherit from the generic abstract MessageHandler<T> instead of implementing IMessageHandler: public class HandlerA : MessageHandler<MessageA> { public override void Execute(MessageA message) { Console.WriteLine("Message A"); } } public class HandlerB : MessageHandler<MessageB> { public override void Execute(MessageB message) { Console.WriteLine("Message B"); } }
How about this for a message router: class Tester { public void Go() { var a = new MessageA(); var b = new MessageB(); var c = new MessageC(); var router = new MessageRouter(); router.RegisterHandler(new HandlerA()); router.RegisterHandler(new HandlerB()); router.Route(a); router.Route(b); router.Route(c); } } class MessageRouter { Dictionary<Type, dynamic> m_handlers = new Dictionary<Type,dynamic>(); public void RegisterHandler<T>(IMessageHandler<T> handler) { m_handlers.Add(typeof(T), handler); } public void Route(dynamic message) { var messageType = message.GetType(); if (m_handlers.ContainsKey(messageType)) { m_handlers[messageType].Handle(message); } else { foreach (var pair in m_handlers) { if(pair.Key.IsAssignableFrom(messageType)) { pair.Value.Handle(message); } } } } } class MessageA { public virtual string A { get { return "A"; } } } class MessageB { public string B { get { return "B"; } } } class MessageC :MessageA { public override string A { get { return "C"; } } } interface IMessageHandler<T> { void Handle(T message); } class HandlerA : IMessageHandler<MessageA> { public void Handle(MessageA message) { Console.WriteLine(message.A); } } class HandlerB : IMessageHandler<MessageB> { public void Handle(MessageB message) { Console.WriteLine(message.B); } }
How about taking a slightly different approach: Instead of registering the type of a handler, why not register the actual handler instance which will process the message? This gives you much greater flexibility in instantiation of the handler, and removes any type ambiguities. The idea is to be able to do this: // have several handler classes class FooMessageHandler : IMessageHandler<Foo> { } class BarMessageHandler : IMessageHandler<Bar> { } // have them instantiated - allows you to pass much more context // than Activator.CreateInstance is able to do var fooMessageHandler = new FooMessageHandler(various params); var barMessageHandler = new BarMessageHandler(various params); // register actual instances HandlerRegistry.Register<Foo>(fooMessageHandler); HandlerRegistry.Register<Bar>(barMessageHandler); // handler registry will simply dispatch the message to // one of the handlers HandlerRegistry.Dispatch(someFooMessage); Not only that, but the approach allows you to register multiple handlers for each message type: // these will all get called when a Foo message is received HandlerRegistry.Register<Foo>(fooMessageHandler); HandlerRegistry.Register<Foo>(someOtherFooHandler); HandlerRegistry.Register<Foo>(yetAnotherFooHandler);
What if you inherit all you messages from common abstract MessageBase and instead of making message handler interface IMessageHandler<T> generic, put constraint on Execute method itself? Namely void Execute<T>(T message) where T : MessageBase. This way you get the desired functionality and your message handler resolver, HandlerRegistry, needs only a minor tweak. Just change return type & constraint from IMessageHandler<T> to IMessageHandler. Below are slightly modified MessageBase, IMessageHandler and HandlerRegistry. (Related dotnetfiddle here https://dotnetfiddle.net/e6M1UA) // Message public abstract class MessageBase { public virtual void Action() // ...for examples sake { Console.WriteLine(GetType().Name); } } // Message handler public interface IMessageHandler { void Execute<T>(T message) where T : MessageBase; } // Resolver public static class HandlerRegistry { private static readonly Dictionary<string, Type> Handlers = new Dictionary<string, Type>(); public static void Register<T, T2>() where T2 : IMessageHandler { Handlers.Add(typeof(T).FullName, typeof(T2)); } public static IMessageHandler Resolve<T>(T parameters) { var type = Handlers[parameters.GetType().FullName]; return (IMessageHandler)Activator.CreateInstance(type); } } Now, if you test it using e.g. following implementations public class Message1 : MessageBase {} public class Message2 : MessageBase { public override void Action() { Console.Write(#"Overriding "); base.Action(); } } public class Message1Handler : IMessageHandler { public void Execute<T>(T message) where T : MessageBase { Console.Write(#"MessageHandler1 > "); message.Action(); } } public class Message2Handler : IMessageHandler { public void Execute<T>(T message) where T : MessageBase { Console.Write(#"MessageHandler2 > "); message.Action(); Console.WriteLine(#"...and then some"); } } With this block of code HandlerRegistry.Register<Message1, Message1Handler>(); HandlerRegistry.Register<Message2, Message2Handler>(); var messages = new List<MessageBase>() { new Message1(), new Message2() }; foreach (var message in messages) { var handler = HandlerRegistry.Resolve(message); handler.Execute(message); } You'll end up with console log MessageHandler1 > Message1 MessageHandler2 > Overriding Message2 ...and then some
Wrapping methods with different signatures, pre-and-post-invocation
How to avoid a pair of repetitive lines before and after invocations in sample below ? Details: This is compileable mock of what is real larger code. Generally it is a layer of proxy classes containing service clients with variety of APIs. The repetitive part is pre- and post- invocation for every method of every client. Unfortunately there is no single signature for all possible methods, the pre- and post- parts need a pointer to client's channel and context. Is it possible to apply something advanced like AOP, Generics, Delegates, Attributes etc. ? Thank you using System; namespace ConsoleApplication { class ClassServiceClient: IDisposable { public Object channel() { return "something"; } public Object context() { return "something other"; } } class ClassA : ClassServiceClient { public Object methodA() { return "something other"; } } class ClassB : ClassServiceClient { public void methodB(string param) { return; } } class ClassAProxy { public Object methodA() { using (ClassA client = new ClassA()) { Program.preparation(client.channel()); //<---- repetitive part Object result = client.methodA(); Program.postinvocation(client.context());//<---- repetitive part return result; } } } class ClassBProxy { public void methodB(string param) { using (ClassB client = new ClassB()) { Program.preparation(client.channel()); //<---- repetitive part client.methodB(param); Program.postinvocation(client.context());//<---- repetitive part return; } } } class Program { public static void preparation(Object channel) { // Do something with channel } public static void postinvocation(Object context) { // Do something with context } static void Main(string[] args) { } } }
If you can use a common base class, you can easily use a public sealed method that does the invocation and a protected abstract method that does the logic, e.g. class ProxyBase{ public void Method(params object[] args){ PreConditions(); Invoke(args); PostConditions(); } protected abstract void Invoke(object[] args); } class ClassAProxy{ protected override void Invoke(object[] args){ client.Method(args[0]); } } You can achieve similar results functionally by declaring a InvocationHandler in your Program class that takes an action: class Program{ public static void Invoke(object[] args, Action action){ PreConditions(); action(); PostConditions(); } } class ClassAProxy{ public void MethodA(int i){ Program.Invoke(() => client.Something(i)); } }