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

时间:2010-07-05 14:41:14

标签: c# asp.net-mvc reflection inversion-of-control castle-windsor

我一直在努力创建自己的IoC容器以用于学习目的。在询问了几个关于它们的问题之后,我被证明创建一个工厂来“解决”这些对象是最好的解决方案(see third solution here)。用户Krzysztof Koźmic显示Castle Windsor实际上可以为您实现此功能。

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

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

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

编辑:发现Reflection.Emit ......这可能是用过的吗?

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

3 个答案:

答案 0 :(得分:7)

这里有两个不同的概念:

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

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


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


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

答案 1 :(得分:5)

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

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

实际上并不复杂:)

答案 2 :(得分:1)

ImpromptuInterface基于接口创建DLR动态代理。它允许您使用静态接口进行动态实现。实际上它甚至有一个基类ImpromptuFactory,它提供了基于接口创建具有动态实现的工厂的起点。