“新建”接口

几天前,我看到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的上下文中,我立刻想到这被用作穷人的编译时dependency injection

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

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

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

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

我知道周末至少有两篇博客文章 – 我的和艾恩德的 。

对于大多数代码,这应该仅仅被视为好奇心。 我认为将dependency injection用于dependency injection是一种滥用,当已建立的IoC / DI框架可以更好地完成工作,并且如此简单。

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

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

所以不行; 不要这样做 – 这只是一个乐趣。