OK I've just implemented a Command-CommandHandler pattern in our application that adds a command object to a queue; then uses dependency injection through Castle Windsor alongside a generic method to get the relevant handler for the command object.
The Command interface is blank like so:
public interface ICommand
{
}
Whilst the CommandHandler interface handles it like so:
public interface ICommandHandler<TCommand> where TCommand : ICommand
{
void Handle(TCommand command);
}
These are then implemented by the commands I wish to send through the queue; then registered in Castle Windsor through a DependencyRegistration wrapper like so:
_dependencyRegister
.AddRegistration<ICommandHandler<TestCommand>, TestCommandHandler>();
So each command that will be added to the queue maps 1 to 1 with a handler; then is registered in Castle Windsor; so we can use a generic method like this to get the relevant CommandHandler for a particular Command object:
private void HandleCommand<T>(T queueItem) where T: ICommand
{
var handler = _dependencyResolver.Resolve<ICommandHandler<T>>();
handler.Handle(queueItem);
}
The final piece is the queue dispatcher method which looks like this:
private void DispatchQueueItem(ICommand queueItem)
{
HandleCommand(queueItem);
}
Right; the issue is that when I pull a command off the queue as an ICommand and pass it to the DispatchQueueItem method; when it is sent to the HandleCommand method the "T" type is always set to the "ICommand" interface; rather than the actual implementation of the interface (TestCommand in the DependencyRegistration sample code).
My question is; how do I set the HandleCommand method to take the Type of the implementation; not the interface?
Change your dispatch method to generic:
private void DispatchQueueItem<T>(T queueItem)
where T: ICommand
{
HandleCommand(queueItem);
}
UPDATE you can force C# to define object type at runtime this way
private static void DispatchQueueItem(ICommand queueItem)
{
HandleCommand((dynamic)queueItem);
}
I think you want it to be of the interface - but you just need to have a method contract defined in there - like:
public interface ICommand
{
void Execute();
}
//Concrete implementation:
public TestCommand : ICommand
{
public void Execute()
{
//Do something
}
}
Then, when you get the ICommand out of DI - you can call queueItem.Execute()
- and this will refer to whatever concrete implementation you've assigned.
Yout queue will lalways dispatch ICommands. So so need to get the type "under the hood":
private void HandleCommand<T>(T queueItem) where T: ICommand
{
var typeParam = queueItem.GetType();
var type = typeof(ICommandHandler<>).MakeGenericType(typeParam);
var handler = _dependencyResolver.Resolve(type);
I'm not sure of the exact sintax. Don't have a project with Castle Windsor at hand.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.