“新建”接口

时间:2009-08-20 02:56:58

标签: c# dependency-injection mocking

几天前,我看到CoClassAttribute以我以前没有想到的方式使用。


[ComImport, CoClass(typeof(Foo)), Guid("787C1303-AE31-47a2-8E89-07C7257B1C43")]
interface IFoo {
    void Bar();
}

class Foo : IFoo {
    public void Bar() {
        Console.WriteLine("Oh retado!");
    }
}

用作:


class CoClassDemo {
    public static void Show() {
        var a = new IFoo();
        a.Bar();
    }
}

这应该不会让我感到惊讶,因为自从.NET Framework早期以来,COM Interop正是这样做的。在.NET Reflector中挖掘COM Interop代码时,我根本没有那么多关注。


method public hidebysig static void Show() cil managed
{
    .maxstack 1
    .locals init (
        [0] class ConsoleApplication1.IFoo a)
    L_0000: nop 
    L_0001: newobj instance void ConsoleApplication1.Foo::.ctor()
    L_0006: stloc.0 
    L_0007: ldloc.0 
    L_0008: callvirt instance void ConsoleApplication1.IFoo::Bar()
    L_000d: nop 
    L_000e: ret 
}

发生的事情是,在COM Interop的背景下,我立刻想到这被用作穷人的编译时依赖注入

所有要做的就是摆脱界面名称上的传统“I”前缀(就像COM Interop一样)。

然后,将更改CoClass属性以将实现交换为另一个,模拟等等。

我预先看到的两个缺点是,当接口和实现部署到不同的程序集时,必须重新编译(这几乎将测试场景限制为开发时间)以及与循环依赖关系相关的最终问题。

有人玩这种技术吗? 还有其他任何缺点吗? 其他用途?

1 个答案:

答案 0 :(得分:10)

我知道周末至少有两篇博文 - mineAyende's

对于大多数代码来说,这只应被视为好奇心。我认为使用它进行依赖注入是一种滥用,当已建立的IoC / DI框架可以更好地完成工作时,简单。

特别是,这种方法依赖于§17.5的逃逸孵化,这是微软特定的规范扩展......你想让你的代码在Mono上运行吗?我没有尝试过,但没有具体的原因它应该在gmcs / dmcs下编译。

Jon有一个better example在具体代码中使用它 - 故意模仿COM,但那是用于使用.NET 4.0 / dynamic。再次;这不适用于大多数“常规”代码。

所以没有; 不要这样做 - 这只是一个乐趣。