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