代码改变世界

Oxite 之 ControllerActionInvoker应用

2009-04-02 17:03  无常  阅读(737)  评论(0编辑  收藏  举报

看Oxite的源码时遇到个很困惑的问题,在Oxite的Controller中,很多Action返回值不是我们常见的ActionResult类型,比如说这里:

    public class PageController : Controller
    {
        //....
        public virtual OxiteModelItem<Page> Item(string pagePath)
        {
            Page page = pageService.GetPage(pagePath);
            if (page == null) return null;
            return new OxiteModelItem<Page>
            {
                Item = page
            };
        }
        //.....
    }

OxiteModeItem是何许人也?起初以为是ActionResult的派生类,是这样吗?到Oxite.ViewModels中我们可以看个究竟,

    public class OxiteModel
    {
        public INamedEntity Container { get; set; }
        public SiteViewModel Site { get; set; }
        public UserViewModel User { get; set; }
        private readonly Dictionary<Type, object> modelItems = new Dictionary<Type, object>();
        public void AddModelItem<T>(T modelItem) where T : class
        {
            modelItems[typeof(T)] = modelItem;
        }
        public T GetModelItem<T>() where T : class
        {
            if (modelItems.ContainsKey(typeof(T)))
                return modelItems[typeof(T)] as T;
            return null;
        }
        //....
    }

并非如我所想,在这个目录中还有几个它儿子,继承层次如下

image

竟然不是派生于ActionResult,只是下原汁原味的Model,纳闷了,MVC中的V到哪里去了?

如果之前没接触过IOC,看Oxite的代码时确实是有点头晕,好不容易才把OxiteControllerActionInvoker翻出来了。先来看下它的代码

namespace Oxite.Infrastructure
{
    public class OxiteControllerActionInvoker : ControllerActionInvoker
    {
        private readonly IFilterRegistry filterRegistry;
        public OxiteControllerActionInvoker(IFilterRegistry filterRegistry)
        {
            this.filterRegistry = filterRegistry;
        }
        protected override ActionResult CreateActionResult(ControllerContext controllerContext, ActionDescriptor actionDescriptor, object actionReturnValue)
        {
            if (actionReturnValue == null)
            {
                controllerContext.Controller.ViewData.Model = new OxiteModel { Container = new NotFoundPageContainer() };
                return new NotFoundResult();
            }
            if (typeof(ActionResult).IsAssignableFrom(actionReturnValue.GetType()))
                return actionReturnValue as ActionResult;
            controllerContext.Controller.ViewData.Model = actionReturnValue;
            return new ViewResult { ViewData = controllerContext.Controller.ViewData, TempData = controllerContext.Controller.TempData };
        }
        //....
    }
}

在这里可以看到个明白,actionReturnValue就是就是控制器中返回的结果,在这里首先判断是否为空,然后判断返回结果的类型是否从ActionResult派生出来的,如果是,说明是个View,直接交出去了,否则就是Model了。

当然这里还离不开另一个类OxiteControllerFactory:

namespace Oxite.Infrastructure
{
    public class OxiteControllerFactory : DefaultControllerFactory
    {
        private readonly IUnityContainer container;
        public OxiteControllerFactory(IUnityContainer container)
        {
            this.container = container;
        }
        protected override IController GetControllerInstance(Type controllerType)
        {
            IController iController = container.Resolve(controllerType) as IController;
            if (typeof(Controller).IsAssignableFrom(controllerType))
            {
                Controller controller = iController as Controller;
                if (controller != null)
                    controller.ActionInvoker = container.Resolve<IActionInvoker>();
                return iController;
            }
            return iController;
        }
    }
}

ControllerFactory看名字就知道是做什么用的了,在控制器创建了之后,直接指定自己的ActionInvoker。

推荐二篇关于ActionInvoker的文章:

http://lostintangent.com/2008/07/03/aspnet-mvc-controlleractioninvoker-part-1/

http://lostintangent.com/2008/07/07/aspnet-mvc-controlleractioninvoker-part-2/

 

from : wuchang.cnblos.com