开发者

What is IOC and why would I want to use Castle Windsor etc in my MVC app? [duplicate]

This question already has answers here: Closed 12 years ago.

Possible Duplicate:

What is IOC? Need some practical code examples to illustrate

I have heard IOC banded about a lot but I'm still not entirely sure what it is and why I would want it. My naive understanding is that it somehow gives you control but I'm not sure what.

I know Castle Windsor is the popular product for ASP.Net MVC but I dont understand what it does. It seems to override the default way ASP.Net MVC handles requests for controllers.

I'm starting a MVC app with Fluent NHibernate and trying to get it configured but all posts seem to suggest using Castle Windsor as well.

Could you please explain exactly what IOC is and why I would want to use Castle Windsor in a ASP.Net MVC app?

T开发者_如何学Gohanks


IOC is a design pattern introduced by Martin Fowler which allows for weaker coupling between different parts of your code. So for example in an ASP.NET MVC application you could use IOC to decouple your controllers logic from the data access logic. The idea behind is that the controller doesn't work with a specific implementation of a repository but uses an interface. It is the responsibility of the code that instantiates the controller to provide a specific implementation: thus the term inversion of control - it is not the component that controls its dependencies, it is the consumer of the control.

So imagine you have defined the following contract:

public interface IUsersRepository
{
    IEnumerable<User> GetAllUsers();
}

And then you could have a controller which depends on this contract:

public class UsersController : Controller
{
    private readonly IUsersRepository _repository;
    public UsersController(IUsersRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        var users = _repository.GetAllUsers();
        return View(users);
    }
}

As you can see the UsersController is completely decoupled from the way users are fetched. It uses a contract and it is the responsibility of the code instantiating this controller to provide a specific implementation of the repository. In the case of ASP.NET MVC this code is the controller factory. The default controller factory built into ASP.NET MVC uses reflection to call the default constructor of the matching controller. In this case there is no default constructor. So you need a custom controller factory. This is where Castle Windsor comes into action.

Now that your controller is decoupled from a specific implementation of the repository you get another very important benefit: you can unit test it in isolation, without depending on anything. You could simply mock/substitute this repository and unit test only the controller logic.


Non-technical translation!

Let's say you have a box full of screwdrivers that you need to use. A screwdriver with a cross head, a magnetic screwdriver with a cross head and an electric magnetic screwdriver with interchangeable heads.

When you first started working, you only had the screwdriver with the cross head in your toolbox and every time you needed to screw something together you would always use this tool.

Later on, you became aware of a problem with screws dropping off of the head when you were trying to screw in a downwards direction, so you switched to using the screwdriver with the magnetic head.

Much later you could afford a whizzy electric screwdriver with all the bells and whistles on it and your efficiency went way up!

Each of these screwdrivers implement the IScrewDriver interface including methods for screw and unscrew. In the real world it's easy to choose which screwdriver to use, in your code, if you create the CrossHeadScrewdriver class in lots of different places, you have to change lots of code if you want to use the ElectricScrewdriver instead.

With inversion of control, you specify in one place in your code that when you want an IScrewDriver it should use the ElectricScrewdriver and all of a sudden changing the ScrewDriver becomes as easy as the real world!


IoC in general and Castle Windsor in particular will not help you until you try. Concept is well described in MVC 2 in Action book. Here is a citate:

One common technique when building applications is to pass application dependencies into the constructor of the controllers. By leveraging various tools, we can automatically wire up these dependencies and provide the arguments without having to write mundane, repetitive code. To enable this for our controllers, we need to take responsibility for creating them...

...

The Inversion of Control principle and dependency injection

Normally when code executes other code, there’s a linear flow of creation and execution. For instance, if I have a class that depends on another class, I will create that class with the new operator, and then execute the class by calling a method. If I used Inversion of Control (IoC), I’d still call methods on the class, but I’d require an instance of the class passed into my constructor. In this manner, I yield control of locating or creating my dependency to the calling code. Dependency injection (DI) is the act of injecting a dependency into a class that depends on it.

Often used interchangeably, IoC and DI yield loosely coupled code and are often used with interfaces. With interfaces, classes declare dependencies as interfaces in the constructor arguments. Calling code then locates appropriate classes and passes them in when constructing the class.

IoC containers come into play to assist with managing this technique when used through an application. There are plenty of IoC containers to choose from, but the favorites at this time seem to be StructureMap (http://structuremap.sourceforge.net), Ninject (http://ninject.org), and Castle Windsor (www.castleproject.org/container). Controllers can leverage dependency injection by declaring their dependencies as constructor parameters. This inverts the control so that the caller is responsible for supplying the dependencies of a class, rather than the class constructing concrete instances itself. It allows you to decouple controllers from concrete instances of its dependencies (such as a repository or service). It’s quite liberating, not to mention that it helps facilitate decoupled unit testing.

When we ask for dependencies in the constructor, we call it constructor injection. There’s another technique called property injection, but it isn’t as apparent that these dependencies are required for the object to do its job. IoC tools can usually do both, but constructor injection is preferred for required dependencies.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜