Asp.net MVS 集成Spring.net机制原理及实现

 

我们都知道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的容器中。

你可能感兴趣的:(asp.net)