我的春秋痴梦第三步:
让所有的增删查改自动化,
不用每次都实例化一个controller然后郁闷的写增删查改的方法。
效果:
根据url 得到要操作的对象,自动对model属性过滤换转,完成CURD生成对应的回传给view。
我的思路:
@1 分析提交的 url /admin/article/create 得到对象
@2 实例化 (article) 对象
@3 根据 (article)对象 权限 找到 (article) 的限制(使用xml)
@4 根据限制 过滤(article)对象
@5 转换和上传(有图片之类的话)
@6 再交给auto controller即直接 增改
@7 根据url对象返回页面
整个想法比较简单。和之前那篇一样让程序更通用更自动化。
其实一开始接触MVC的时候就又这个想法了,当时没想好该怎么做增改这两块。
前段时间看了老D分析Suteki.Shop 介绍了 里面一个自动脚手架
两个周前我把他定下计划之中 I will make it!
废话不多说。
@1 可以想我一样自己分析url 也可以取得 route 里面的 controller的值

当然 在这里 我并不推荐这样.直接取值更方便。
@2 实例化(article) 对象并装配进去表单的值

在上一篇中我提到了不知道如何转换可空类型后来发现了这篇文章 感谢乐于分享的牛人们。(感谢cnblogs)
其中一个自己写的Init的扩展类似前一篇,就不瞎贴代码了。获得一个对象类似前一篇的根据string类型,
得到类型都是静态工厂直接new一个出来。
@3 根据(article)对象用户的权限 找到 (article) 的限制和转换(使用xml)
@3.1 我这里选择了xml没有使用加attribute的方式,为的是更改后不用重新编译。

这里我的想法比较多,但是很多都还没有实现。
比如根据url生成验证的id版本,根据权限选择不同的url,类似html的css 可以自定义 验证和转换。
@3.2 再来看看 Linq 2 XML 进行读取和解析 xml

我的xmlHelper

比较简陋 。。我是实用主义。
这样我们就可以在
foreach (var element in fileups){}// <DownUrl fileup="/UpFile/,*,上传失败" />
中间专心写自己的处理了。
@3.3延迟执行
在这里的时候我,我突然发现如果在这里以检查上传没问题就即时上传的话,可能他并没有通过后面的检查
而导致白白的消耗性能和硬盘。这里我先把要执行的方法先保存起来。(感谢重典兄的指点)
private List < Func < bool >> functions = new List < Func < bool >> ();
@4 根据限制 过滤(article)对象
使用非常简单 依次添加,遍历执行即可。整个东西有3个需要做的,
第一个是文件上传
第二个指定转换
第三个验证,验证你也可以用其他的,比如分离自带的那个验证为自己用。


验证我这里就没有贴了比上面两者都简单 。
指定方法的执行我采用的是调用我指定的一个对象下面的方法,本来 是想调用任意的,在xml那里写全对象的
namespace那些就可以调用,后来还是放弃了,感觉不实用。方法也只是一个单参数的方法。比如
md5加密和指定转换 普通用户发的文章为 未审核等。
@5 保存和上传(有图片之类的话)
var result = functions.All(a => a.Invoke()); // 都满足 返回 true
@6 再交给auto controller即直接 增改
var ir = IRR.GetRepository(urlHelper.modelName.str2type());
ir.InsertOnSubmit(model);
ir.SubmitChanges();
@7 根据url对象返回页面。这里给出我在controller中的实现:

提醒一下
1暂时那个 ModelState.IsValid 验证没有任何意义,因为传进来的model是object。
2如果不知道我那个 public IRepository Ir;怎么出来的可以参见我的上一篇。
在这里可以写成
public class AutoController < T > : Controller where T : class , new ()
就可以使用验证了。我不这样做是因为 我不想每次都要实例化一个。来模板继承。
但是目前我采用的做法仍然是 依靠一个 具体类 继承 我那个自动类。然后让原本访问具体类的增删查改方法的
去访问自动类了。而这时我们只需要在xml里面写明规则那么一切OK。
至此 问题依然 没有解决 那就是 由于 依托于具体类继承自动类。每次还是得实例化类。
(我是后台:可不可以不要那么多XXXcontroller文件啊!)
我们其实可以在 Global.asax 那里 拦截请求。
不给controller执行 而是 构造自己的 RouteHandler 解析路由 和HttpHandler 转到view
此处参考重典兄的 route
实现的思路
1在 global 处 截断 指定格式的请求
2构造自己的RouteHandler 进行解析
3 分发给对应的 httphandler
public static void RegisterRoutes(RouteCollection routes)
{
routes.Add( new Route( " {page}.np " , new MyRouteHandler())); // 解析.aspx
}
我指定以.np后缀访问的都是我自动类处理的天下。
我的想法是这样 /area(Default)/model/action/id.np
同时对应view页面的位置统一。其实现非常简单。参看重典兄的就可以做出来。
这时我们会遇到几个问题
1如何传值到页面 viewdata 肯定不行了,因为controller与我们渐行渐远。
2此时view上的XXhelper ,HTML 的方法都没了,以前构造html的方法都没了。
对于第一点 我们可以使用session 只需要加上IRequiresSessionState
public class MyPage : IHttpHandler, IRequiresSessionState
这里有个有趣的问题,但是我又不知道怎么回事。在构造函数执行的时候,session null不可用。
而构造完后才开始有session。这是怎么回事呢。
对于第二点我就有点无奈了。我参考源码,暂时还没把他整个方法移植过来。郁闷的是,由于那个是模板的,而我们
已经没有了页面MODEL了。所以比较麻烦。很多方法里也内嵌了MODEL。即时勉强移植过来还是会存在一些不能用的
语法但是又存在。感觉不爽。
走到这里的时候我感觉到很吃力。 丢掉了controller之后,我还有一大堆view丢不掉,还有怎么和以前的路由兼容?
不然的话整个view上路由的重写也有点小麻烦。
感觉使用框架的便利,自己也被绑架到框架上了。自己的代码原始积累应该是与框架无关的啊!这样才能形成自己的
代码库。
最后由于无法丢弃以前的view暂时使用前一种方法,来优化自己的CMS。走到第三步。这次的感觉有点沉重。
越发觉得自己的渺小和对知识认识的浅薄,当时以为委托 很简单,自己遇到了问题需要解决才发现,好多其实都
没有理解好。另一点沉重也许是对未来的一种迷茫吧。基于框架的代码还是我们的代码吗?昨天有个牛人说他为了
不让自己的代码有隐患,尽量不用第三方的框架SSH那些都不用。而是做自己的基于基础类库的原始积累。
也许JAVA和.NET不一样吧。我始终坚持,一步一步优化,一步一步积累。把时间精力花在最需要解决问题的地方,
慢慢的用自己的代码替换别人的框架,像我这次这样替换掉controller,也许有一天就用自己的东西替换了
mvc了呢。虽然没有mvc的通用,但最合适自己。不是嘛?