代码改变世界

Unity 在MVC上的应用(上:思路整理)

2011-05-15 11:01  bugfly  阅读(3451)  评论(7编辑  收藏  举报

前言

  卧病数月,颓废的日子。以前向往的未来一一被真几个月的辛酸打碎了,但未来依然要吃饭,所以打算写一个简短MVC系列来回顾IOC的应用,过中将会有实际开发中解决常见问题的方法。

  注意:本系列每一篇文章和上一篇并无必然的承接关系,但所应用到的技术点是有先后顺序的,你将会从文章的应用上发现。

系列目录

  Unity 在MVC上的应用(上:思路整理)

  Unity 在MVC上的应用(中:Repository)

  Unity 在MVC上的应用(下:ORM)

  Unity 在MVC上的应用(扩展篇:JQuery AJAX)

  Unity 在MVC上的应用(扩展篇:事务控制-前篇ActionFilter)

  Unity 在MVC上的应用(扩展篇:事务控制-后篇Unit Of Work)

  Unity 在MVC上的应用(扩展篇:日志管理NLog)

正题

  在上篇,我会通过一个简单的MVC例子来做一个DEMO,而并没有使用Unity,目的在于告诉对IOC应用场合不清晰的朋友面对什么情况使用IOC。各个这个例子很简单 (*^__^*) 嘻嘻……

本次教程使用的是MVC开发框架,结合Repository模式来展开。上篇暂时没有使用到Unity。

一如既往,先看看DEMO的物理结构图。

1

那些文件我就不一一叙述了,也不难理解。

先看看大致的运行流程。

Step 1

2

 登录账号是HuntSoul 密码是123456 (*^__^*) 嘻嘻……

Step 2

3

这里登录成功的画面。我们点开“任务列表” Check Check今日有什么任务 ~(X X)~

Step 3

4

返回一下 XD,点开“打开仓库”!看看我们仓库的武器 XD

Step 4

5

好了,大致的流程就是这个摸样,正如我所说很简单~下面我们来看看这些简单而丑陋的代码 XD。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class Entity
{
public int ID { get; set; }
}
}

Entity类作用在于标示对象。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class Account:Entity
{
public string AccountID { get; set; }
public string AccountPwd { get; set; }
public string LickName{get;set;}
public string Age { get; set; }
public string Email { get; set; }
public string Cellphone { get; set; }

public List<Task> Tasks { get; set; }
public List<StoreHouse> Stores { get; set; }
}
}

这个是我们的 账号模型,和传统的游戏账号相比,当然这个简单很多,不过基于教程,我们无需太过复杂,恰到理解就可以了,以上英文我想你们都不用我一一解释其属性了吧?XD 要提一提的是,本教程没有使用到数据库,所以对于DB First的程序员,可能比较难理解,不过这个刚好是给你们一个新的视野去尝试面向对象(OO),这种方式貌似就是业界所说的Code First吧?或者我所理解的Model First~XD. 还是要解释一下关键的地方。 Account类有两个聚合列表对象Task(任务)和StoreHouse(仓库),是一对多关系。这里的仓库有点纠结,写教程的时候一时想歪了,明白我说的朋友就凑合看吧,哈哈。墨迹了这么多,下面的Model代码就不一一解释了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class Task : Entity
{
public string TaskName { get; set; }
public string TaskContent { get; set; }
public string TaskStatus { get; set; }

public Account Account { get; set; }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class StoreHouse : Entity
{
public string GoodsName { get;set;}
public int GoodsNum{get;set;}
public float GoodsKg { get; set; }

public Account Account { get; set; }
}
}

好了,刚才说到我没使用数据库,那图片上的数据如何解释?恩,聪明的你已经想到了,那个DBContext是一个数据生成类,说白了就是一个假的数据库,为了测试,这个必需的,大家无需太过在意我的方式,你喜欢的可以随意模拟一个DB,用NBuilder也可以~不一一解释用法。来看看DBContext

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class DBContext
{
public List<Account> Accounts { get; set; }

public DBContext()
{
Accounts
= new List<Account>();

Account n_account
= new Account()
{
ID
= 1,
AccountID
= "HuntSoul",
AccountPwd
= "123456",
LickName
= "桀骜的灵魂",
Age
= "44",
Cellphone
= "139XXXXXXXXX",
Email
= "31580941X@qq.com",
Tasks
= new List<Task>() {
new Task(){
ID
=1,
TaskName
="Unity And MVC practice Demo2",
TaskContent
="...",
TaskStatus
="已完成"
}
,
new Task(){
ID
=2,
TaskName
="每日打酱油",
TaskContent
="...",
TaskStatus
="未完成"
}
},
Stores
= new List<StoreHouse>()
{
new StoreHouse(){
ID
=1,
GoodsName
="希利欧之魂",
GoodsNum
=10,
GoodsKg
=80
},
new StoreHouse(){
ID
=2,
GoodsName
="海格力斯之袭",
GoodsNum
=30,
GoodsKg
=150
},
new StoreHouse(){
ID
=3,
GoodsName
="克罗莉斯之吻",
GoodsNum
=25,
GoodsKg
=132
},
}
};
Accounts.Add(n_account);
}
}
}

此时此刻,我们应该看看Controller类了。打开HomeController

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using UnityAndMVC2_Demo2.Models;

namespace UnityAndMVC2_Demo2.Controllers
{
[HandleError]
public class HomeController : Controller
{
public AccountRepository _AccountRepository = new AccountRepository();
public TaskRepository _TaskRepository = new TaskRepository();
public StoreHouseRepository _StoreHouseRepository = new StoreHouseRepository();

[HttpGet]
public ActionResult Login()
{
return View();
}

[HttpPost]
public ActionResult Login(FormCollection Model)
{
Account n_account
=new Account();

UpdateModel(n_account);

var n_dbUser
=_AccountRepository.find(n_account.AccountID, n_account.AccountPwd);

if (n_dbUser != null)
{
HttpContext.Session[
"User"] = n_account.AccountID;
return View("Index", n_dbUser);
}

return View();
}

public ActionResult Index()
{
return View();
}

public ActionResult TaskDetails()
{
List
<Task> n_taskList = this._TaskRepository.find(HttpContext.Session["User"].ToString());

return View(n_taskList);
}

public ActionResult StoreHouseDetails()
{
List
<StoreHouse> n_storeHouseList = this._StoreHouseRepository.find(HttpContext.Session["User"].ToString());

return View(n_storeHouseList);
}
}
}

不算复杂,就几个ACTION.对应的就是登录画面和菜单管理画面的操作。不墨迹意思了。

如代码上可以看到,有三个Repository实体类。见以下代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class AccountRepository
{
public DBContext _Context=new DBContext();

public Account find(int ID)
{
var n_result
= from a in _Context.Accounts
select a;
return n_result.ToList().FirstOrDefault();
}

public Account find(string AccountID,string AccountPwd) {
var n_result
= from a in _Context.Accounts
where a.AccountID.Equals(AccountID)&&a.AccountPwd.Equals(AccountPwd)
select a;
return n_result.ToList().FirstOrDefault();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class TaskRepository
{
public DBContext _Context = new DBContext();

public List<Task> find(string AccountID)
{
var n_result
= from a in _Context.Accounts
where a.AccountID.Equals(AccountID)
select a;

return n_result.FirstOrDefault().Tasks;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace UnityAndMVC2_Demo2.Models
{
public class StoreHouseRepository
{
public DBContext _Context = new DBContext();

public List<StoreHouse> find(string AccountID)
{
var n_result
= from a in _Context.Accounts
where a.AccountID.Equals(AccountID)
select a;

return n_result.FirstOrDefault().Stores;
}
}
}

这三个Repository实体,内容都是那么相似。。聪明的你一定在笑哥,为什么不重构一下,对对对,那个什么泛型Repository,不用急,在最后一篇将会重构Repository的。这里暂不列出内容,,,因为中篇还没写,(*^__^*) 嘻嘻……

我们再看看我们的HomeController代码,你会发现,有不少直接new的对象,就是那三个Repository啦,全篇重点就是这里,直接new的结果是,过分耦合,repository的生命周期完全和Controller绑定了,结果就是,有一天要重构这几个Repository实体的方法,你修改的就不是单单那几个要重构的Repository了,而是每个引用到他们的地方,可能你还觉得问题不明显,这样吧,如果有1000个Repository实体,有100个Controller引用它们,重构它们原本find的行为,改为Lookout()行为。。这个悲剧能看到了吧?所以呢,我们不能直接就new它们到其他类里面,要降低耦合程度,为未来的维护做好准备,什么方法可以解开耦合呢?可以告诉你的很多,不过,我觉得最好的方式就是使用IOC容器,通过容器去关系注入关系,恩~完了,下篇我们将会引入Unity来解开这段耦合关系。很久没用过了。给点时间我,(*^__^*) 嘻嘻……

最后附上本篇的DEMO代码

DEMO