代码之家  ›  专栏  ›  技术社区  ›  Erik Philips Gabriel Costa

我的MVC定制控制器工厂工作,但它能更好吗?

  •  2
  • Erik Philips Gabriel Costa  · 技术社区  · 14 年前

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

    下面的代码是针对一个小的内部项目的,因此请记住让我开始。

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

    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)
        {
        }
    }
    

    创建了我自己的控制器工厂,允许我将模型工厂注入控制器。

    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;
        }
    }
    

    最后添加代码,将concrete类注入工厂,注入到创建的控制器中。

        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
    
            RegisterRoutes(RouteTable.Routes);
    
            ControllerBuilder.Current.SetControllerFactory(new DIControllerFactory(new LinqSqlModelFactory()));
        }
    

    我唯一没有探索过的领域(我认为我现在不感兴趣)是创建一个 web.config 用于动态创建 ModelFactory . 这是可行的,但如果我完全错过了船,靠近了,或者我在现场,我会感兴趣吗?

    1 回复  |  直到 14 年前
        1
  •  4
  •   Remo Gloor    14 年前

    而不是重写CreateController使用

    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    

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

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