"Newing up" 接口

7

几天前,我看到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 反编译器中查看 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 互操作的上下文中,我立刻设想它被用作“穷人的编译时依赖注入”。
所要做的就是摆脱接口名称上的传统“I”前缀(与COM互操作一样)。
然后只需要改变 CoClass 属性来交换实现,进行模拟等。
我看到的两个缺点是必须重新编译(这基本上将测试方案限制在开发时间),以及接口和实现部署到不同程序集时可能出现的循环依赖问题。
有人尝试过这种技术吗?其他缺点?其他用途?

8
在高中时上过工艺课吗?“用适合的工具完成适合的工作。”使用为COM交互设计的工具去完成完全不同的任务是一个糟糕的想法。这样会使下一个需要维护代码的人无法理解它。记住,下一个人很可能是你,在数年后已经忘记为什么要做这个疯狂的事情。 - Eric Lippert
1个回答

10

我知道这个话题在周末至少有两篇博客-我的Ayende 的

对于大多数代码来说,这只应该被视为一种好奇心。当已经有IoC/DI框架可以更好、更简单地完成任务时,我认为滥用这种方式作为依赖注入是不妥的。

特别地,这种方法依赖于§17.5的逃生口,这是一个Microsoft特定的规范扩展...你想让你的代码在Mono上运行吗?我没有尝试过,但是没有具体的 理由表明它应该在gmcs/dmcs下编译。

Jon有一个更好的例子,使用它来故意模拟COM,但那只是为了玩耍.NET 4.0/dynamic。同样地,在大多数“常规”代码中不会应用到这个例子。

所以不要这样做——这只是一个有趣的旁白。


目前而言,我也将其视为一种好奇心。我仍在我的头脑后台线程中处理这个信息片段,我还想知道是否有其他“创意”使用这种技术的方法。 - Alfred Myers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接