I have the following code ...
My Command handler:
public class MyHandler : IHandler
{
// I Want to get rid of this method
public override void ExecuteOperation(BaseOperation operation)
{
// This is a work-around
this.ExecuteOperation(operation as SpecificOperation);
}
public override void ExecuteOperation(SpecificOperation operation)
{
// Do actual work here
}
}
My Command handler dispatcher:
private dynamic FindOperationHandler(TBaseProvisioningOperation operation)
{
... some logic here
return Activator.CreateInstance(handlerType, ... args here ...)
}
My consumer code
public void PerformProvisioningOperation(BaseOperation operation)
{
// Find the correct handler for this operation
var operationHandler = this.FindOperationHandler(operation as TBaseProvisioningOperation);
// make it execute the operation
// NOTE: 'operation' is SpecificOperation type, for example
operationHandler.ExecuteOperation(operation); // <--- problem is here
}
The issue is that when I create an instance of my handler class with the Activator.CreateInstance
and pass it a boxed object (i.e. as "BaseOperation
") parameter, .NET looks for a method in the handler, which has a parameter of the base type, instead of automatically invoking the one which can handle the object if it were unboxed (i.e. explicitly cast).
Of course we have SpecificOperation : BaseOperation
In other words: I want when I execute operationHandler.ExecuteOperation(operation);
, .NET to invoke ExecuteOperation(SpecificOperation operation)
instead of ExecuteOperation(BaseOperation operation)
, because the operation parameter is boxed (i.e. it IS SpecificOperation
but is downcast-ed as BaseOperation
).
How do I achieve that?
Edit:
public interface IHandler<TOperation> where TOperation : BaseOperation
{
/// <summary>
/// TODO: Get rid of this method
/// </summary>
/// <param name="operation">The operation to execute - boxed</param>
void ExecuteOperation(BaseOperation operation);
/// <summary>
/// Executes the operation
/// </summary>
/// <param name="operation">The operation to execute - unboxed</param>
void ExecuteOperation(TOperation operation);
}
Assuming you're using dynamic
here to achieve Double-Dispatch, the problem is that you're casting the wrong object.
It's the operation
variable that needs to be casted (in order to defer overload resolution until runtime), not the operationHandler
.
Try this instead:
operationHandler.ExecuteOperation(operation as dynamic);
And you can avoid the redundant dynamic
definition on your FindOperationHandler
:
private IHandler FindOperationHandler(TBaseProvisioningOperation operation)
{
return Activator.CreateInstance(handlerType, ... args here ...) as IHandler;
}
See Double-Dispatch