However when it come to dealing with Generic Interface, we need to tell Ninject what Generic Interface bind to what Concrete Class. Just like the following syntax:
this.kernel = new StandardKernel();
this.kernel.Bind<IMessageHandler<PersonMessage>>().To<PersonMessageHandler>(); this.kernel.Bind<IMessageHandler<CoffeeMessage>>().To<CoffeeMessageHandler>();
Here is what you need to do: Install these 2 NuGet Packages:
- using Ninject;
- using Ninject.Extensions.Conventions;
this.kernel.Bind(x => x.FromThisAssembly() .SelectAllClasses().InheritedFrom(typeof(IMessageHandler<>)) .BindAllInterfaces());
I need to process a collection of different type of message. Each type has it own handler class.
Here are two types of message: PersonMessage and CoffeeMessage, that both are inherited from BaseMessage class.
public class BaseMessage
{
public string Name { get; set; }
}
public class PersonMessage : BaseMessage
{
public int Age { get; set; }
}
public class CoffeeMessage : BaseMessage
{
public int Volume { get; set; }
}
public interface IMessageHandler<T> where T : BaseMessage
{
void Handle(T message);
}
public class PersonMessageHandler : IMessageHandler<PersonMessage>
{
public void Handle(PersonMessage message)
{
//Do something useful with the person message here
}
}
public class CoffeeMessageHandler : IMessageHandler<CoffeeMessage>
{
public void Handle(CoffeeMessage message)
{
//Do something useful with the coffee message here
}
}
var messageList = new List<BaseMessage>(); messageList.Add(new PersonMessage() { Name = "Jame", Age = 20 }); messageList.Add(new CoffeeMessage() { Name = "Mocha", Volume = 1 }); messageList.Add(new PersonMessage() { Name = "Ken", Age = 15 }); messageList.Add(new CoffeeMessage() { Name = "Cappuccino", Volume = 1 }); messageList.Add(new PersonMessage() { Name = "Tim", Age = 35 }); messageList.Add(new CoffeeMessage() { Name = "Late", Volume = 1 }); foreach (var message in messageList)
{
if(message is PersonMessage)
{
var handler = this.kernel.Get<IMessageHandler<PersonMessage>>();
handler.Handle(message as PersonMessage);
}
else if(message is CoffeeMessage)
{
var handler = this.kernel.Get<IMessageHandler<CoffeeMessage>>();
handler.Handle(message as CoffeeMessage);
}
}
this.ProcessMessage(message);
public void ProcessMessage<T>(T message) where T : BaseMessage
{
// Mam Baa Jam Baa code to construct the right message handler type
Type handlerType = typeof(IMessageHandler<>);
Type[] typeArgs = { message.GetType() };
Type constructed = handlerType.MakeGenericType(typeArgs);
// Here we are the Chosen One message handler
var handler = this.kernel.Get(constructed);
// Invoke handle message
var methodInfo = constructed.GetMethod("Handle");
methodInfo.Invoke(handler, new[] { message });
}