在不创建实现的情况下实现接口(动态代理?)

The*_*Sky 2 c# reflection asp.net-mvc castle-windsor inversion-of-control

我一直在努力创建自己的IoC容器用于学习目的.在询问了几个关于它们的问题之后,我被证明创建一个"解决"对象的工厂是最好的解决方案(参见第三个解决方案).用户KrzysztofKoźmic表明Castle Windsor实际上可以为您实现这一点.

我整个上午都在阅读CW的来源.我知道当调用Resolve时,它会"返回界面".这个接口如何"拦截"调用(因为后面没有实现)并调用它自己的方法?

我知道这里有一些反思诡计,这真是太神奇了.我根本不是用户如何"拦截".我试着用git冒险从兔子洞里冒险,但我迷路了.如果有人能指出我正确的方向,那将非常感激.

另外 - 创建一个类型化的工厂是否会依赖于调用代码中的容器?在ASP.NET MVC术语中,这就是我所看到的.

编辑:发现Reflection.Emit ...这可能是什么用的?

EDIT2:我越来越关注这一点,自动创建工厂听起来越复杂.我可能最终只是坚持使用重复的代码.

Dan*_*ant 7

这里有两个不同的概念:

  1. 依赖注入仅仅实例化实现接口的现有类.例如,您可能有一个实现IMyServices的MyServices类.IoC框架为您提供了各种方法来指定当您请求IMyServices时,它将解析为MyServices的实例.可能会有一些IL Emit魔法来设置工厂或辅助方法,但实际的实例只是你定义的类.

  2. Mocking允许您实例化一个实现接口的类,而不必实际编写该类.正如您所想,这通常会使用Reflection和IL Emit.通常,发出的IL代码非常简单,将大部分工作委托给用C#编写的方法.模拟的大部分复杂性与指定方法本身的行为有关,因为框架通常允许您使用流畅的语法指定行为.有些像Moles一样,只是让你指定一个委托来实现这个方法,虽然Moles可以做其他更疯狂的事情,比如将调用重定向到静态方法.


为了进一步说明,您实际上并不需要使用IL来实现IoC功能,但这通常有助于避免重复的Reflection调用的开销,因为Reflection相对昂贵. 以下是有关Castle Windsor正在做什么的一些信息.


为了回答你的问题,我发现最有用的地方是OpCodes课程.这是IL中可用功能以及OpCodes功能的一个很好的总结.它本质上是一种基于堆栈的汇编语言(无需担心寄存器),但是强类型,并且具有对象符号和概念的一流访问,如类型,字段和方法. 是一篇很好的Code Project文章,介绍了IL的基础知识.如果您有兴趣,我还可以发送一些我在过去几年创建的帮助类,用于我自己的Emit代码.


Krz*_*mic 5

使用Castle DynamicProxy库实现类型化工厂.它会动态生成一个实现接口的类型,并通过接口将所有对该类型的调用转发给拦截器.

它对您的代码没有任何依赖性.界面是在您控制的程序集中创建的,您不参考Windsor.在其他程序集(应用程序的入口点)中,您告诉Windsor关于该界面并告诉它使其成为工厂,Windsor了解您的界面并对其进行处理.这就是它的荣耀中的控制倒置.

它实际上并不复杂:)