views:

97

answers:

2

I've been working on creating my own IoC container for learning purposes. After asking a couple questions about them, I was shown that creating a factory to "resolve" the objects was the best solution (see third solution here). User Krzysztof Koźmic showed that Castle Windsor actually can implement this for you.

I've been reading the source of CW all morning. I know when Resolve is called, it "returns the interface". How does this interface "intercept" calls (since there is no implementation behind) and call it's own methods?

I know there's obviously some reflection trickery going on here and it's quite amazing. I'm just not at all user how the "interception" is done. I tried venturing down the rabbit hole myself on git, but I've gotten lost. If anyone could point me in the right direction it'd be much appreciated.

Also - Wouldn't creating a typed factory have the dependency on the container inside the calling code? In ASP.NET MVC terms, that's what it seems to me.

EDIT: Found Reflection.Emit... could this be what's used?

EDIT2: The more and more I look into this, the more complicated it sounds to automatically create factories. I might end up just sticking with the repetitive code.

+3  A: 

There are two separate concepts here:

  1. Dependency injection merely instantiates an existing class that implements the interface. For example, you might have a MyServices class that implements IMyServices. IoC frameworks give you various ways to specify that when you ask for an IMyServices, it will resolve to an instance of MyServices. There might be some IL Emit magic going on to set up the factory or helper methods, but the actual instances are simply classes you've defined.

  2. Mocking allows you to instantiate a class that implements an interface, without actually having to code that class. This does usually make use of Reflection and IL Emit, as you thought. Typically the emitted IL code is fairly simple, delegating the bulk of the work to methods written in C#. Most of the complexity of mocking has to do with specifying the behavior of the method itself, as the frameworks often allow you to specify behavior with a fluent syntax. Some, like Moles, simply let you specify a delegate to implement the method, though Moles can do other, crazier things like redirecting calls to static methods.


To elaborate a bit further, you don't actually need to use IL to implement IoC functionality, but this is often valuable to avoid the overhead of repeated Reflection calls, since Reflection is relatively expensive. Here is some information on what Castle Windsor is doing.


To answer your question, the most helpful place I found to start was the OpCodes class. This is a good summary of the available functionality in IL and how the OpCodes function. It's essentially a stack-based assembly language (no registers to worry about), but strongly-typed and with first-class access to object symbols and concepts, like types, fields, and methods. Here is a good Code Project article introducing the basics of IL. If you're interested, I can also send you some helper classes I've created over the last few years that I use for my own Emit code.

Dan Bryant
@Dan - Thanks for the comment. I'm trying to *use* "mocking" for my IoC container that I'm trying to make. Castle Windsor uses some sort of technique to create a "typed factory" that implements the specified interface. If you read the link I posted from Krzysztof, you'll see what I mean. I don't want to use a third party library as this is all for my own learning. Would you have any resources on class generation? EDIT: I know I don't *need* to use IL, I'm just curious as to how it's done. Thanks! :)
TheCloudlessSky
@Dan - Thanks for this. I'm going to start reading. I might not implement this functionality because it does seem so extreme. But, I am going give this a look because it's very interesting. Thanks!
TheCloudlessSky
@TheCloudlessSky, IL is a lot of fun, as you can do some very powerful things with it. It does take a lot of work, though and the Emit methods are quite persnickety (they don't provide any checking that you included the correct arguments, so it's very easy to mistakenly create IL code that fails to verify or blows up at runtime.) If you play with it, just remember that peverify.exe is your friend.
Dan Bryant
+2  A: 

The typed factory is implemented using Castle DynamicProxy library. It generates a type on the fly that implements the interface and forwards all calls to that type, you make via the interface, to the interceptor.

It imposes no dependency in your code. The interface is created in your assembly, that you control, where you don't reference Windsor. In other assembly (entry point to the app) you tell Windsor about that interface and tell it to make it a factory and Windsor learns about your interface and does stuff with it. That's Inversion of Control in its glory.

It's actually not that complicated :)

Krzysztof Koźmic
@Krzysztof - Thanks for the answer. So, I take it the Castle DynamicProxy library uses Reflection.Emit?
TheCloudlessSky
@Krzysztof - Never mind. I went digging through the source of DynamicProxy and found all sorts of neat things (and yes it's using Reflection.Emit). Thanks! :)
TheCloudlessSky