如何摆脱这段代码中的反射调用?
我正在构建一个简单的“总线”作为概念证明。我不需要任何复杂的东西,但我想知道如何最好地优化以下代码。我使用 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
}
}
I'm building a simple "bus" as a proof of concept. I do not need anything complicated but am wondering how best to optimise the following piece of code. I'm using Autofac as a container to resolve commands as open generics but actually executing the commands is currently being done via reflection as the incoming command cannot be cast to a concrete type in the code. See code - marked up with // BEGIN // END - this is currently being done with reflection. Is there a way to do this without using reflection?
// 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
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
怎么样(仅显示更改的部分):-
这里的关键是使
Publish
方法通用,这意味着您获得对类型的类型引用T
命令,然后可用于进行转换。与以前一样,类型参数约束只是确保只能传递ICommand
。顺便说一句 - 我已经测试过它并且它有效,这是完整的代码:-
-- 更新 --
正如 Peter Lillevold 所指出的,您还应该考虑向 IOC 容器方法添加类型参数,如下所示:-
这将简化你的调用者像这样:-
这是你原来问题的一个侧面,但对于 IOC 接口来说似乎是一个明智的设计。
How about this (only the changed parts shown):-
The key here is to make the
Publish
method generic, which means that you get a type referenceT
to the type of the command, which can then be used to make the cast. The type parameter constraints simply ensure that only anICommand
can be passed, as before.BTW - I've tested this and it works, here's the full code:-
-- UPDATE --
As pointed out by Peter Lillevold, you should also think about adding a type parameter to your IOC container method as follows:-
this will simplify your caller like so:-
This is a side point to your original question, but would seem a sensible design for the IOC interface.
这有效吗?您的 IoC 正在返回对象,请考虑返回 T,这样您就不必像下面那样处理类型歧义。
Does this work? Your IoC is returning object, consider returning T instead then you wont have to handle type ambiguity as done below.