views:

116

answers:

6

After reflecting upon all the great answers I received to my previous question about modeling my code to maximize code re-use, I started wondering if it would be possible to assign the interface to an object at runtime instead of when it is coded.

Take, for example, a simplified portion of code from my previous question:

public class OutboxManager
{
    private IVendorMessenger _VendorMessenger;

    //This is the default constructor, forcing the consumer to provide
    //the implementation of IVendorMessenger.
    public OutboxManager(IVendorMessenger messenger)
    {
         _VendorMessenger = messenger;
    }

    public void DistributeOutboxMessages()
    {
        VendorMessenger.SendMessageToVendor()
                      _OutboxMgrDataProvider.MarkMessageAsProcessed(om)
    }

}

Currently, if someone wants to consume this class, they have to code a class that implements IVendorMessenger and provide it during initialization as a parameter:

 var MyOutboxManger = new OutboxManager(new MyVendorMessenger())

What if, instead of hard-coding the interface parameter, it instead gets assinged at runtime? This way, I could compile a dll for a class that implements IVendorMessenger, drop it into the same folder that OutboxManagerExecutable exists, and it will wire everything up at run time. I suppose, using this logic, I could figure out a way to drop multiple implementations of IVendorMessenger in the same folder and design the executable to be smart enough to iterate through all appropriate dlls and consume them accordingly.

Is this type of functionality possible in .NET 4?

+3  A: 

Check out the Managed Extensibility Framework (MEF). It can automatically compose the dependencies of your application just as you describe. It shipped with .NET 4.0.

HTH,
Kent

Kent Boogaart
I've heard of MEF before but I wasn't sure if it could be used to solve this kind of problem. I wonder what it looks like to use.
Ben McCormack
@Ben: there are plenty of examples on the website I linked to.
Kent Boogaart
+1  A: 

Do you think about using MEF? It allows you to create application build of many modules.

You can see it here

ŁukaszW.pl
Ooops.. looks like I was a 30 seconds too late ;)
ŁukaszW.pl
+1  A: 

EDIT: I just realized that I misunderstood the question. The question does not, in fact, seem to be about assigning an interface to an object at runtime, but rather about late binding type names.

I'll leave the answer up as Community Wiki, in case someone else has the same misconception.


This is usually called Interface Injection, and has been on the wishlist for both the CLI and the JVM for as long as they exist.

Especially the people who write implementations for programming languages that were not natively designed for the CLI or the JVM, like JRuby, XRuby, Ruby.NET, IronRuby, IronPython, Jython, Rhino, IronJS, etc. have this feature high on their wishlist, because it means that they do no longer have to maintain a parallel type hierarchy and marshal objects back and forth between the two.

However, they don't seem to be on the horizon any time soon, or indeed at all, although there is at least a strawman spec for the JVM with an accompanying partial prototype implementation for the Da Vinci Machine.

Jörg W Mittag
@Jörg thanks for your response. I think I am in fact looking for a solution in the style of late-binding, but I wasn't sure how to word it. Regarding your answer, though, how is *Interface Injection* different from *Dependency Injection*?
Ben McCormack
+1  A: 

You should be able to do this just fine (class wise) in .Net 2.0/3.0 with Generics.

You can also use Reflection to load a dll during runtime.

Tony Abrams
A: 

MEF is great, but if you'd like a few simple examples of what you're describing versus a feature-rich library, I've seen it described as a 'plugin architecture':

Corbin March
+1  A: 

This is a pretty common use case for reflection. The .NET API gives you the pieces you need to:

  1. Find all of the .dlls in a directory: Directory.GetFiles()
  2. Load those assemblies at runtime: Assembly.LoadFile()
  3. Iterate through the types in each assembly: Assembly.GetTypes()
  4. For each type, see if it implements your interface: Type.IsAssignableFrom()
  5. If it does, get and invoke its constructor to create one: Type.GetConstructor()

After that, you've got an Object that you can cast to IVendorMessenger and pass it in.

munificent
This is a really helpful answer. Much thanks!
Ben McCormack
You can mark this answer as accepted too. ;)
munificent