Activator.CreateInstance 并将装箱对象传递给调用的方法

Activator.CreateInstance and passing a boxed object to an invoked method

我有以下代码...

我的命令处理程序:

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
  }
}

我的命令处理程序调度程序:

private dynamic FindOperationHandler(TBaseProvisioningOperation operation)
{
  ... some logic here
  return Activator.CreateInstance(handlerType, ... args here ...)
}

我的消费代码

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
}

问题是,当我使用 Activator.CreateInstance 创建我的处理程序 class 的实例并向其传递一个装箱对象(即作为“BaseOperation”)参数时,.NET在处理程序中寻找一种方法,该方法具有基本类型的参数,而不是自动调用可以处理对象的方法(如果对象未装箱(即显式转换))。

当然有SpecificOperation : BaseOperation

换句话说:我希望在执行 operationHandler.ExecuteOperation(operation); 时,.NET 调用 ExecuteOperation(SpecificOperation operation) 而不是 ExecuteOperation(BaseOperation operation),因为操作参数是装箱的(即它是 SpecificOperation 但沮丧的是 BaseOperation).

我该如何实现?

编辑:

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);
    }

如果完整代码在 C# 中,您应该避免 returning dynamicActivator.CreateInstance 是 returning 一个 Object 而不是动态的。 当 properties/methods 不是强类型时,动力学用于脚本语言之间的互操作。

很遗憾您没有描述 IHandler 界面,但是...

我认为;您面临的问题是您的接口定义了您的 class 必须实现 void ExecuteOperation(BaseOperation operation); 这样您的 FindOperationHandler 应该 return 一个 IHandler.

private IHandler FindOperationHandler(TBaseProvisioningOperation operation)
{
    ... some logic here
    return (IHandler)Activator.CreateInstance(handlerType, ... args here ...)
}

对于您的处理程序:

public class MyHandler : IHandler
{

    public override void ExecuteOperation(BaseOperation operation)
    {
        var operation = (SpecificOperation)operation;
        // Do actual work here
    }
}

假设您在这里使用 dynamic 来实现双分派,问题是您投错了对象。

需要转换的是 operation 变量(以便将重载决策推迟到运行时),而不是 operationHandler.

试试这个:

operationHandler.ExecuteOperation(operation as dynamic);

并且您可以避免 FindOperationHandler 上的冗余 dynamic 定义:

private IHandler FindOperationHandler(TBaseProvisioningOperation operation)
{
  return Activator.CreateInstance(handlerType, ... args here ...) as IHandler;
}

Double-Dispatch