Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"Newing up" Interfaces

A couple of days ago, I saw the CoClassAttribute being used in a way I haven't imagined before.


[ComImport, CoClass(typeof(Foo)), Guid("787C1303-AE31-47a2-8E89-07C7257B1C43")]
interface IFoo {
    void Bar();
}

class Foo : IFoo {
    public void Bar() {
        Console.WriteLine("Oh retado!");
    }
}

being used as:


class CoClassDemo {
    public static void Show() {
        var a = new IFoo();
        a.Bar();
    }
}

That should have not surprised me since COM Interop does exactly that since the early days of the .NET Framework. I simply haven’t paid that much attention when digging through COM Interop code in .NET Reflector.


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 
}

What happened is that out of the context of COM Interop, I immediately I envisioned this being used as a poor man’s compile time dependency injection.

All there is to do is get rid of the conventional "I" prefix on the interface's name (as does COM Interop).

Then it would be a matter of changing the CoClass attribute to swap an implementation for another, mocking, etc.

Two drawbacks I see upfront are having to recompile (which pretty much limits testing scenarios to development time) and eventual problems surrounding circular dependencies when interfaces and implementations are deployed to different assemblies.

Has anybody played with this technique? Any other drawbacks? Other uses?

like image 594
Alfred Myers Avatar asked Aug 20 '09 02:08

Alfred Myers


1 Answers

I know this got at least two blog posts on the weekend - mine and Ayende's.

For most code, this should be treated merely as a curiosity. I think it would be an abuse to use this for dependency injection, when established IoC/DI frameworks can do the job so much better, and so simply.

In particular, this approach relies on the escape hatch of §17.5, a Microsoft-specific extension to the spec... do you want your code to run on Mono? I haven't tried it, but there is no specific reason that it should compile under gmcs / dmcs.

Jon had a better example of using it in concrete code - for deliberately mocking COM, but that was for toying with .NET 4.0 / dynamic. Again; this wouldn't apply to most "regular" code.

So no; don't do it - it is just a fun aside.

like image 101
Marc Gravell Avatar answered Nov 03 '22 23:11

Marc Gravell