簡體   English   中英

如何擺脫這段代碼中的反射調用?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM