问题描述
我最近发现可以 "用 "nofollow">CoClassAttribute
指定默认实现.
I recently discovered that it's possible to "new up" an interface in C# by decorating the interface with the CoClassAttribute
to specify a default implementation.
[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 互操作,但我想知道这是否是将接口与通用类库中的默认实现相关联的合理方法.
I'm aware that this feature exists primarily to support COM-interop, but I was wondering if this would be a reasonable way to associate interfaces with default implementations in generic class-libraries.
我有两个问题:
这样做有什么问题吗?我不是 COM 互操作方面的专家,我不知道这是否会对 POCO 产生任何负面影响.我没有运行任何主要测试,但我的示例的 IL 似乎没问题(
FooImpl
上的普通newobj
指令而不是调用Type.GetTypeFromCLSID
和Activator.CreateInstance
).
Are there any gotchas with doing this? I'm not an expert on COM-interop and I don't know if this will have any negative impact on POCOs. I haven't run any major tests, but the the IL for my example seems ok (a normal
newobj
instruction onFooImpl
rather than calls toType.GetTypeFromCLSID
andActivator.CreateInstance
).
即使这会顺利进行,是否还有其他原因(比如从 API 设计的角度)来避免这种情况?
Even if this would work smoothly, are there other reasons (say from an API-design perspective) to avoid this?
推荐答案
您不应该这样做的关键原因是您正在对不需要它的对象实例启动 COM 生命周期管理..NET 现在必须进行一些 COM 互操作,包括安全堆栈遍历、单元线程检查和 addref/release 内容.
The key reason you shouldn't do this is that you are starting the COM lifecycle management on an instance of an object that doesn't need it. .NET will now have to do some COM interop that includes a security stack walk, apartment threading checks, and addref/release stuff.
相反,我会考虑查看依赖注入(控制模式反转)和公共服务定位器模式.我将专注于理解构造函数注入,因为它是依赖管理的首选模式.
Instead, I would consider looking at dependency injection (inversion of control pattern) and the Common Service Locator Pattern. I would focus on understanding constructor injection as it is the preferred pattern for dependency management.
这是我在我的库中所做的.假设我想编写一个日志服务(人为的例子).我将有两个核心组件:
Here's what I do in my libraries. Let's say I want to write a logging service (contrived example). I would have two core components:
MyStuff.Logging.Contracts - 这里是我声明 ILogger 接口的地方MyStuff.Logging - 在这里我可以编写不同的日志实现,例如 FileLogger、DatabaseLogger 等.
MyStuff.Logging.Contracts - Here is where I would declare the ILogger interface MyStuff.Logging - Here is where I would write the different logging implementations I might have like FileLogger, DatabaseLogger, etc.
然后在我的应用程序中,我将使用 Ninject 或 Unity(DI 容器)将 ILogger 与默认实现相关联.
Then in my application I would use either Ninject or Unity (DI containers) to associate ILogger with the default implementation.
这篇关于(ab)使用 CoClassAttribute 为接口提供默认实现是否可以?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!