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

时间:2016-05-26 07:24:36

标签: c# reflection activator

我有以下代码......

我的命令处理程序:

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

我的消费者代码

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创建处理程序类的实例并将其传递给一个盒装对象(即&#34; BaseOperation&#34;)参数时,.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);
    }

2 个答案:

答案 0 :(得分:1)

假设您在此处使用dynamic来实现Double-Dispatch,问题是您正在施放错误的对象。

需要进行转换的operation变量(为了将重载解析推迟到运行时),而不是operationHandler

请改为尝试:

operationHandler.ExecuteOperation(operation as dynamic);

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

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

请参阅Double-Dispatch

答案 1 :(得分:0)

如果完整代码在C#中,则应避免返回dynamicActivator.CreateInstance正在返回Object而不是动态。 当属性/方法没有强大的类型时,动态是用于脚本语言之间的互操作。

太糟糕了,你没有描述IHandler界面,但......

我想;您面临的问题是您的界面定义了您的班级必须实施void ExecuteOperation(BaseOperation operation);这样您的FindOperationHandler应该返回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
    }
}