net搭建热插拔式web框架(重造Controller)
由于.net MVC 的controller 依赖于HttpContext,而我们在上一篇中的沙箱模式已经把一次http请求转换为反射调用,并且http上下文不支持跨域,所以我们要重造一个controller。
我们在写mvc项目的时候经常会用到ViewBag、ViewData,那我们就先声明这两个变量:
1
2
|
public dynamic ViewBag = new DynamicViewBag(); public ViewDataDictionary ViewData = new ViewDataDictionary(); |
当然还可以根据自己的需要构建更多的特性。
我们在一个网络请求中避免不了会携带一些参数,那这些参数该如何传到沙箱中呢?我们定义了一个RefRequestEntity类,他负责对我们的参数经行打包,把参数打包后对象作为参数传到沙箱内部:
在.net mvc中我们可以返回ActionResult,在ActionResult内部调用时才会做出真正的Response(更多细节请参考mvc实现原理),当然它在执行的整个过程中都是由HttpContext贯穿的,我们没有了HttpContext,我们就只自己构造一些Response方法。
返回View()结果:
mvc中由ViewEngine来编译执行我们写好的视图文件(.aspx、.cshtml),而我们则借助于RazorEngine来编译执行razor视图文件,它可以支持我们常用的ViewBag、using、layout等(更多请见RazorEngine)。在本篇中我们还是把精力放回controller的实现中,关于视图的实现我们在下一篇中在讲。我们先看一下一个View的简单实现:
1
2
3
4
5
6
7
8
9
10
|
/// <summary>返回试图的执行结果 /// </summary> /// <returns></returns> protected string View() { var tKey = Engine.Razor.GetKey(getActionPath(), ResolveType.Global); //getActionPath:获取action对应的视图文件key值。 return new CompileView().RunCompile(tKey, null , null , ViewBag); //返回执行结果 } |
View()的执行结果是一段html代码。这样我们在请求一个action的时候,就可以正常的呈现一个页面了。下边是一个Controller基类的实现,它完成了View、PartialView的实现Demo:
我们上边列出了对Razor编译执行的简单过程,还是那句话,RazorEngine的更多实现细节将在下一篇讲解。那么现在问题来了,我们得到了html代码或者说我们执行玩自己的业务逻辑以后如何把这个结果输出呢(即HttpResponse)?
我们定义了一个RefRespondEntity类,它来承载返回结果,并把结果返回到沙箱外层的调用者,再由这个调用者将这个RefRespondEntity对象Response出去:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
[Serializable] public class RefRespondEntity { public RefRespondEntity(RespondType type) { ResultType = type; } /// <summary>返回结果的数据类型 /// </summary> public RespondType ResultType { get ; set ; } /// <summary>返回结果的内容 /// 如果是ResultType=_Redirect那么ResultContext=301 /// 如果是ResultType=_Stream那么ResultContext="文件名.zip",当然这个文件名可以随意定义 /// </summary> public object ResultContext { get ; set ; } /// <summary>返回结果的文件流 /// </summary> public byte [] ResultStream { get ; set ; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
|
//一个action的demo public RefRespondEntity Index4(RefRequestEntity param) { object AA = param.Request[ "A" ]; object BB = param.Request[ "B" ]; object CC = param.Request[ "C" ]; RefRespondEntity result = new RefRespondEntity(RespondType._String); result.ResultContext = View(); object tt = ViewBag.test; return result; } |
1
|
var result = sandBox.InvokeMothod(urlEntity.controller, urlEntity.action, paras); //sandBox是一个沙箱的实例化对象 |
1
|
RequestHandle.ResposeResult(respond, result); //输出结果 |
转载请注明出处:http://www.cnblogs.com/eric-z/p/5028243.html