"新建"接口

Alf*_*ers 7 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!");
    }
}

Run Code Online (Sandbox Code Playgroud)

用作:


class CoClassDemo {
    public static void Show() {
        var a = new IFoo();
        a.Bar();
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该不会让我感到惊讶,因为自.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 
}

Run Code Online (Sandbox Code Playgroud)

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

所有要做的就是摆脱接口名称上的传统"I"前缀(就像COM Interop一样).

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

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

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

Mar*_*ell 10

我知道周末至少有两篇博客文章 - 我的艾恩德的.

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

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

Jon有一个更好的例子,在具体的代码中使用它 - 故意模仿COM,但这是用于使用.NET 4.0/dynamic.再次; 这不适用于大多数"常规"代码.

所以不行; 不要这样做 - 这只是一个乐趣.