[英]How can I get rid of the reflection invoke in this piece of code?
我正在構建一個簡單的“公共汽車”作為概念證明。 我不需要復雜的東西,但想知道如何最好地優化以下代碼。 我將Autofac用作容器來將命令解析為開放的泛型,但實際上執行當前的命令是通過反射完成的,因為傳入的命令無法轉換為代碼中的具體類型。 參見代碼-用// BEGIN // END標記-當前正在通過反射完成。 有沒有一種方法可以不用反射呢?
// IoC wrapper
static class IoC {
public static object Resolve(Type t) {
// container gubbins - not relevant to rest of code.
}
}
// Handler interface
interface IHandles<T> {
void Handle(T command);
}
// Command interface
interface ICommand {
}
// Bus interface
interface IBus {
void Publish(ICommand cmd);
}
// Handler implementation
class ConcreteHandlerImpl : IHandles<HelloCommand> {
public void Handle(HelloCommand cmd) {
Console.WriteLine("Hello Command executed");
}
}
// Bus implementation
class BusImpl : IBus {
public void Publish(ICommand cmd) {
var cmdType = cmd.GetType();
var handler = IoC.Resolve(typeof(IHandles<>).MakeGenericType(cmdType));
// BEGIN SLOW
var method = handler.GetType().GetMethod("Handle", new [] { cmdType });
method.Invoke(handler, new[] { cmd });
// END SLOW
}
}
怎么樣(僅顯示更改的部分):
// 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);
}
}
此處的關鍵是使Publish
方法通用,這意味着您將獲得命令類型的類型引用T
,然后可將其用於進行強制類型轉換。 與以前一樣,類型參數約束僅確保只能傳遞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);
}
}
-更新-
正如Peter Lillevold指出的那樣,您還應該考慮如下向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界面而言似乎是明智的設計。
這樣行嗎? 您的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
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.