2016-05-26 1 views
1

У меня есть следующий код ...Activator.CreateInstance и передавая коробочный объект в вызываемом метод

My Command Обработчик:

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 и передаю ему объект в штучной упаковке (т. как параметр «BaseOperation»), .NET ищет метод в обработчике, который имеет параметр базового типа, вместо автоматического вызова того, который может обрабатывать объект, если он был распакован (т. е. явно лишен).

Конечно, мы имеем SpecificOperation : BaseOperation

Другими словами: я хочу, когда я исполняю operationHandler.ExecuteOperation(operation);, .NET для вызова ExecuteOperation(SpecificOperation operation) вместо ExecuteOperation(BaseOperation operation), так как параметр операции в штучной упаковке (т.е. IS SpecificOperation, но подавленным-е изд, как BaseOperation).

Как это достичь?

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

Вы должны избегать возвращения 'dynamic' если полный код находится в C#. –

+0

Каков фактический тип, возвращаемый 'FindOperationHandler'? Кроме того, что такое 'TBaseProvisioningOperation'? Существуют ли какие-либо дженерики? – haim770

+0

@JeroenvanLangen, я предполагаю, что 'dynamic' используется здесь для достижения Double Dispatch – haim770

ответ

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

+0

Ты БОГ. Спасибо, 'как динамический' в параметре решил мою проблему! –

0

Вы должны избегать возвращения dynamic если полный код находится в C#. Activator.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 
    } 
} 
+0

Я отредактировал мой вопрос, чтобы включить определение интерфейса обработчика. Кроме того, спасибо за ваш ответ, но моя цель - не бросать. Я хочу использовать параметр строго типизированного метода, который достигается с помощью генериков в интерфейсе IHandler. –

Смежные вопросы