4

我最近发现可以在 C# 中“新建”一个接口,方法是用 装饰接口CoClassAttribute以指定默认实现。

[ComImport, Guid("579A4F68-4E51-479A-A7AA-A4DDC4031F3F"), CoClass(typeof(FooImpl))]
public interface IFoo
{
    void Bar();
}

public class FooImpl : IFoo
{
    public void Bar() { }
}

...

// Constructs a FooImpl
IFoo foo = new IFoo();

我知道此功能的存在主要是为了支持 COM 互操作,但我想知道这是否是将接口与通用类库中的默认实现相关联的合理方法。

我有两个问题:

  1. 这样做有什么问题吗?我不是 COM 互操作方面的专家,我不知道这是否会对 POCO 产生任何负面影响。我没有运行任何主要测试,但我的示例的 IL 似乎没问题(一个正常的newobj指令FooImpl而不是调用Type.GetTypeFromCLSIDand Activator.CreateInstance)。

  2. 即使这会顺利进行,是否还有其他原因(例如从 API 设计的角度)来避免这种情况?

4

2 回答 2

2

您不应该这样做的关键原因是您正在对不需要它的对象的实例启动 COM 生命周期管理。.NET 现在必须进行一些 COM 互操作,包括安全堆栈遍历、单元线程检查和 addref/release 内容。

相反,我会考虑查看依赖注入(控制模式的反转)和公共服务定位器模式。我将专注于理解构造函数注入,因为它是依赖管理的首选模式。

这是我在我的图书馆所做的。假设我想编写一个日志服务(人为的例子)。我将有两个核心组件:

MyStuff.Logging.Contracts - 这里是我要声明 ILogger 接口的地方 MyStuff.Logging - 这里是我要编写不同的日志实现的地方,我可能有 FileLogger、DatabaseLogger 等。

然后在我的应用程序中,我将使用 Ninject 或 Unity(DI 容器)将 ILogger 与默认实现相关联。

于 2011-11-11T17:38:20.627 回答
-2

使用智能评论:

    /// <summary>
    /// Explain here all about interface
    /// </summary>

而不是破解属性,因为它可能会在使用您的类的其他人的半反射实现中适得其反。使用反射的工具可以使用属性,智能感知用于文档。

当然,一些遗留工具在读取您的 /// 评论时会遇到问题,但它们也无法读取您的属性。

于 2011-11-11T13:12:18.783 回答