Как я могу избавиться от отражения отражения в этом куске кода?

Я строю простую «шину» в качестве доказательства концепции // IoC статический класс- обертка IoC { открытый статический объект Resolve ( Type t ) { // контейнерные объекты - не имеет отношения к остальной части кода. } } // Интерфейс интерфейса обработчика IHandles < T > { void Handle ( команда T ); } // Интерфейс интерфейса команд ICommand { } // Интерфейс интерфейса шины IBus { void Publish ( ICommand cmd ); } // Класс реализации обработчика ConcreteHandlerImpl : IHandles < HelloCommand > { public void Handle ( HelloCommand cmd ) { Console . WriteLine ( «Команда Hello выполнена» ); } } // Класс реализации шины BusImpl : IBus { public void Publish ( ICommand cmd ) { var cmdType = cmd . GetType (); var handler = IoC . Разрешить ( typeof ( IHandles <>). MakeGenericType ( cmdType )); // НАЧАЛО МЕДЛЕННО var method = handler . GetType (). GetMethod ( «Дескриптор» , новый [] { cmdType }); метод . Invoke ( обработчик , новый [] { cmd }); // КОНЕЦ МЕДЛЕННЫЙ } } . Мне не нужно ничего сложного, но мне интересно, как лучше оптимизировать следующий фрагмент кода. Я использую Autofac в качестве контейнера для разрешения команд как открытых обобщений, но на самом деле выполнение команд в настоящее время выполняется с помощью отражения, поскольку входящая команда не может быть приведена к конкретному типу в коде. Посмотрите код - размеченный с помощью // BEGIN // END - это в настоящее время делается с отражением. Есть ли способ сделать это без использования отражения?

// Handler interface
interface IHandles<T> where T : ICommand {
    void Handle(T command);
}

// Bus interface
interface IBus {
    void Publish<T>(T cmd) where T : ICommand;
}

// Bus implementation
class BusImpl : IBus {
    public void Publish<T>(T cmd) where T : ICommand {
        var handler = (IHandles<T>)IoC.Resolve(typeof(IHandles<T>));
        handler.Handle(cmd);
    }
}

c#,reflection,command,autofac,bus,

2

Ответов: 2


против 5 принят

Как насчет этого (показаны только измененные детали):

Publish

Ключевым моментом здесь является сделать Tметод универсальным, что означает, что вы получаете ссылку Tна тип для типа команды, которую затем можно использовать для выполнения приведения. Ограничения параметров типа просто гарантируют, что только an ICommandможет быть передано, как и раньше.

Кстати - я проверил это, и это работает, вот полный код: -

public static void Main(){
   new BusImpl().Publish(new HelloCommand());
}

// IoC wrapper
static class IoC {
    public static object Resolve(Type t) {
        return new ConcreteHandlerImpl();
    }
}

// Handler interface
interface IHandles<T> where T : ICommand {
    void Handle(T command);
}

// Command interface
interface ICommand {
}


// Handler implementation
class ConcreteHandlerImpl : IHandles<HelloCommand> {
    public void Handle(HelloCommand cmd) {
        Console.WriteLine("Hello Command executed");
    }
}

public class HelloCommand:ICommand{}

// Bus interface
interface IBus {
    void Publish<T>(T cmd) where T : ICommand;
}

// Bus implementation
class BusImpl : IBus {
    public void Publish<T>(T cmd) where T : ICommand {
        var handler = (IHandles<T>)IoC.Resolve(typeof(IHandles<T>));
        handler.Handle(cmd);
    }
}

-- ОБНОВИТЬ --

Как отметил Питер Лиллевольд, вам также следует подумать о добавлении параметра типа в метод контейнера IOC следующим образом:

// IoC wrapper
static class IoC {
    public static T Resolve<T>() {
        ...
    }
}

это упростит ваш звонок так:

// Bus implementation
class BusImpl : IBus {
    public void Publish<T>(T cmd) where T : ICommand {
        var handler = IoC.Resolve<IHandles<T>>();
        handler.Handle(cmd);
    }
}

Это побочный вопрос к вашему первоначальному вопросу, но он может показаться разумным для интерфейса МОК.


Это работает? Ваш IoC возвращает объект, рассмотрите возможность возврата T вместо этого, тогда вам не придется обрабатывать неоднозначность типа, как сделано ниже.

public void Publish(ICommand cmd) {
    var cmdType = cmd.GetType();
    var handler = IoC.Resolve(typeof(IHandles<>).MakeGenericType(cmdType)) as IHandles<ICommand>;
    if (handler != null)
    {
        // BEGIN SLOW
        handler.Handle(command);
        // END SLOW
    }
    //else throw some exception
}
C #, отражение, команда, autofac, автобус,
Похожие вопросы