Is it possible to (ab) use CoClassAttribute to provide a default implementation for an interface?

I recently discovered that I โ€œupgradeโ€ an interface in C # by decorating the interface with CoClassAttribute to indicate the 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(); 

I know that this function exists mainly for supporting COM-interop, but I was wondering if this would be a reasonable way to associate interfaces with default implementations in universal class libraries.

I have two questions:

  • Are there any problems with this? I am not a COM-interop expert, and I do not know if this will have any negative impact on POCOs. I did not run any large tests, but the IL for my example looks fine (the usual newobj instruction on FooImpl instead of calls to Type.GetTypeFromCLSID and Activator.CreateInstance ).

  • Even if it works smoothly, are there other reasons (say, from an API perspective) to avoid this?

+4
c # api-design com coclass
source share
2 answers

The key reason you shouldn't do this is that you start COM lifecycle management in an instance of an object that it does not need. Now, .NET will have to do some COM interaction, which includes a stack of security stacks, streaming checks on apartments, and addref / release materials.

Instead, I would consider looking for dependencies (inverse of the control pattern) and the shared services locator pattern. I would focus on understanding constructor injection, as it is the preferred template for dependency management.

Here is what I do in my libraries. Let's say I want to write a logging service (a far-fetched example). I would have two main components:

MyStuff.Logging.Contracts - Here I have to declare the ILogger interface MyStuff.Logging - this is where I will write the different logging implementations that FileLogger, DatabaseLogger, etc. may have.

Then in my application, I would use either Ninject or Unity (DI containers) to bind ILogger to the default implementation.

+2
source share

Use intelisense comments:

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

instead of hacking attributes, as this can have unpleasant consequences for another semi-reflex implementation using your class. Attributes should be used by tools that use reflection, intelisense for documentation.

Of course, some obsolete tools will have problems reading your /// comments, but they will also not be able to read your attributes.

-2
source share

All Articles