我的MVC Custom ControllerFactory可以工作,但它会更好吗?

时间:2010-11-27 08:08:55

标签: asp.net-mvc-2 dependency-injection

我看过Ninject,StructureMap和其他依赖注入和服务定位器框架,但这个问题更多的是关于学习它如何工作以及什么可以更好。更重要的是,我对查看Framework的依赖注入源代码并不感兴趣,但是要了解它是如何在实践/代码中从头到尾实现的。

下面的代码适用于一个小型的内部项目,所以请记住,让我开始吧。

这是我将域模型返回给控制器的界面。我已经决定,由于项目的规模(小),控制器的单个接口是可以接受的。

interface IModelFactory
{
    IEnumerable<User> GetUsers();
    User GetUser(Guid UserID);
    bool Add(User User);
    bool Delete(User User);
    bool Update(User User);
    IEnumerable<Car> GetCars();
    Car GetCar(Guid CarID);
    bool Add(Car Car);
    bool Delete(Car Car);
    bool Update(Car Car);
}

每个控制器都继承自DIBaseController,因此我不必为每个控制器创建私有成员。

public abstract class DIBaseController : Controller
{
    protected IModelFactory ModelFactory { get; set; }

    public DIBaseController(IModelFactory ModelFactory)
    {
        this.ModelFactory = ModelFactory;
    }
}

public class HomeController : DIBaseController
{
    public HomeController (IModelFactory ModelFactory)
        : base(ModelFactory)
    {
    }
}

创建了我自己的Controller Factory,允许我将我的ModelFactory注入Controllers。

internal class DIControllerFactory : DefaultControllerFactory 
{
    private IModelFactory _ModelFactory;

    internal DIControllerFactory(IModelFactory ModelFactory)
    {
        this._ModelFactory = ModelFactory;
    }

    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        IController result = null;
        string thisnamespace = this.GetType().Namespace;
        //This could be improved I bet.
        Type controller = Type.GetType(thisnamespace.Substring(0, thisnamespace.IndexOf('.')) + ".Controllers." + controllerName + "Controller");

        if (controller != null
            && controller.IsSubclassOf(typeof(DIBaseController)))
        {
            result = (IController)Activator.CreateInstance(controller, new object[] { this._ModelFactory });
        }
        else
        {
            result = base.CreateController(requestContext, controllerName);
        }

        return result;
    }
}

最后添加代码将Inject the Concreate类注入Factory以注入已创建的控制器。

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        ControllerBuilder.Current.SetControllerFactory(new DIControllerFactory(new LinqSqlModelFactory()));
    }

我没有探索的唯一区域(我认为我现在不感兴趣)是创建一个web.config部分来动态创建ModelFactory。这有效,但我很感兴趣,如果我完全错过了船,靠近,或者我是否被发现?

1 个答案:

答案 0 :(得分:4)

而不是覆盖CreateController使用

protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)

它为您提供控制器类型,并且您的实现的第一部分已过时。

您必须改进的下一点是分析构造函数的参数并传递使用某些配置创建的那些参数的实例,而不是猜测只有一个参数IModelFactory。