ASP.NET MVC 整合 Spring.net(1)- Controller进容器

我们都知道Asp.net MVC自有一套执行机制。
通过分析MVC的MvcHandler关键代码

 

ProcessRequest
        protected internal virtual void ProcessRequest(HttpContextBase httpContext) {
            AddVersionHeader(httpContext);

            
// Get the controller type
            string controllerName = RequestContext.RouteData.GetRequiredString("controller");

            
// Instantiate the controller and call Execute
            IControllerFactory factory = ControllerBuilder.GetControllerFactory();
            IController controller 
= factory.CreateController(RequestContext, controllerName);
            
if (controller == null) {
                
throw new InvalidOperationException(
                    String.Format(
                        CultureInfo.CurrentUICulture,
                        MvcResources.ControllerBuilder_FactoryReturnedNull,
                        factory.GetType(),
                        controllerName));
            }
            
try {
                controller.Execute(RequestContext);
            }
            
finally {
                factory.ReleaseController(controller);
            }
        }

 

 

我们可以认为MVC中Controller都是基于工厂模式来创建对象的。
 
但是要利用Spring.net实现IOC和AOP,就必须管理这个框架中具体对象的创建工作。
即通过配置文件的方式决定一个具体对象的生或死!
Objects
<objects xmlns="http://www.springframework.net/">
  
  
<object id="Demos.Domain.Object">
    
<property name="Target">
      
<object type="Demos.Domain.Object,Demos.Domain">
        
<property name="Manager" ref="Demos.Domain.Manager"/>
      
</object>
    
</property>
  
</object>
</objects>

 

 
但是MVC框架自己的运行机制决定了Controller的创建不会经过Spring。
 
幸好,MVC留下了一个叫做SetControllerFactory的扩展。
即,程序运行之初我们就可以用自己的ControllerFactory替换默认的ControllerFactory.

        protected void Application_Start()
        {
            //用自定义的构造工厂替换默认的
            ControllerBuilder.Current.SetControllerFactory(typeof(Demo.Core.ControllerFactory));

            RegisterRoutes(RouteTable.Routes);
        }

 

 
这样我们自己的工厂进行替换默认的Controller工厂后,就可以控制Controller的创建了。
 

我们自己的Controller工厂的代码

ControllerFactory
using System.Web.Mvc;
using System.Web.Routing;
using Spring.Context;

namespace Demo.Core
{
    
public class ControllerFactory : IControllerFactory
    {
        
/// <summary>
        
/// Default ControllerFactory
        
/// </summary>
        private static DefaultControllerFactory defalutf = null;

        
public IController CreateController(RequestContext requestContext, string controllerName)
        {
            
string controller = controllerName + "Controller";
            IApplicationContext ctx 
= Container.GetContext();

            
if (ctx.ContainsObject(controller))
            {
                
object controllerf = ctx.GetObject(controller);
                
return (IController)controllerf;
            }
            
else
            {
                
if (defalutf == null)
                {
                    defalutf 
= new DefaultControllerFactory();
                }
                    
                
return defalutf.CreateController(requestContext, controllerName);
            }
        }

        
public void ReleaseController(IController controller)
        {
            IApplicationContext ctx 
= Container.GetContext();

            
if (!ctx.ContainsObject(controller.GetType().Name))
            {
                
if (defalutf == null)
                {
                    defalutf 
= new DefaultControllerFactory();
                }

                defalutf.ReleaseController(controller);
            }
        }
    }
}

 

 

 Spring.net 容器包装的代码

 

Container
using System;
using System.Collections;
using System.Collections.Generic;
using Spring.Context;
using Spring.Context.Support;

namespace Demo.Core
{
    
public class Container
    {
        
/// <summary>
        
/// 获取应用程序上下文.
        
/// </summary>
        
/// <returns><see cref="IApplicationContext"/>应用程序上下文.</returns>
        public static IApplicationContext GetContext()
        {
            
if (FApplicationContext == null)
            {
                FApplicationContext 
= ContextRegistry.GetContext();
            }
            
return FApplicationContext;
        }

        
/// <summary>
        
/// 获取应用程序上下文.
        
/// </summary>
        
/// <param name="name"><see cref="IApplicationContext"/>应用程序上下文名称.</param>
        
/// <returns><see cref="IApplicationContext"/>应用程序上下文.</returns>
        public static IApplicationContext GetContext(string name)
        {
            
return ContextRegistry.GetContext(name);
        }

        
/// <summary>
        
/// 获取对象.
        
/// </summary>
        
/// <typeparam name="T">对象的类型.</typeparam>
        
/// <param name="id">标识.</param>
        
/// <returns></returns>
        public static T GetObject<T>(string id)
        {
            
return (T)GetContext().GetObject(id);
        }

        
/// <summary>
        
/// 获取对象类表.
        
/// </summary>
        
/// <typeparam name="T">对象的类型.</typeparam>
        
/// <returns></returns>
        public static IList<T> GetObjects<T>()
        {
            IEnumerable items 
= GetContext().GetObjectsOfType(typeof(T));
            IList
<T> objects = new List<T>();
            
foreach (DictionaryEntry item in items)
            {
                objects.Add((T)item.Value);
            }
            
return objects;
        }

        [ThreadStatic]
        
private static IApplicationContext FApplicationContext;
    }
}

 

 

然后我们再新建个Demos.Controllers的项目。

using System.Web.Mvc;

namespace Demo.Controllers
{
    public class DemoController : Controller
    {
        public ViewResult Index()
        {
            ViewData["Message"] = "Welcome to IOC MVC";
            return View();
        }
    }
}

 

 
相应Dll的配置文件
<?xml version="1.0" encoding="utf-8" ?>
<objects xmlns="http://www.springframework.net/">
  <object id="DemoController" type="Demo.Controllers.DemoController, Demo.Controllers" singleton="false" >
  </object>
</objects>

 

并把配置文件设置为嵌入资源

然后再在Web.config中添加相应配置

 

Web.config
  <sectionGroup name="spring">
      
<section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" />
      
<section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
  
</sectionGroup>

  
<spring>
    
<context>
      
<resource uri="config://spring/objects" />
      
<resource uri="assembly://Demo.Controllers/Demo.Controllers/Controllers.xml" />
    
</context>
    
<objects xmlns="http://www.springframework.net" />
  
</spring>

 

 

 
测试运行,我们可以发现这个DemoController已在Spring的容器中。
posted @ 2010-02-07 13:28  默蛇  阅读(877)  评论(0编辑  收藏  举报