在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
今天无意间看到了Unity Application Block (以下简称Unity),感觉很不错,用起来挺方便的说。于是一时兴起写了这个留言本的小示例。数据库操作采用的NHibernate,UI直接用的 ASP.NET Mvc了。项目基于VS2010 + SQLServer 2005 ,就一个表的增删改查操作很简单。目的是为了体验下Unity的Ioc功能。
国际惯例,先上个项目结构图 项目只是演示使用,未建立公共类和配置项抽象出来等工作,各个项目如下: Guestbook.Biz 业务层,具体业务实现。这里只实现了增删改查 Guestbook.Dal 持久层,基于NHibernate的ORM映射。实现增删改查 Guestbook.IBiz 业务层接口,给UI引用实现解藕。UI层不直接引用具体业务类,实现面向接口 Guestbook.IDal 持久层接口,给Biz引用实现解藕。方便更换不同数据库持久类(PS;虽然NHibernate 已经可以支持多库,这里纯为了娱乐) Guestbook.Model 持久实体,NHibernate的映射文件也放到这个类库里面了 Guestbook.Unity 简单封装了一下Unity,传入相应接口即可New相应的在Web.Config中配置的具体业务类 Guestbook.Web UI层,ASP.NET Mvc项目。控制器直接引用的业务接口IBiz和Model还有Unity其它全部不引用
采取从下往上依次说各层的东西。首先从数据库。。。。(略)---从持久层说起吧。持久层采用了NHibernate基本配置和映射配置就不说了(hkgoogle),首先在Guestbook.Dal中写了一个NHibernateHelper帮助类,代码如下:
代码
/// <summary>
/// NHibernate操作辅助类 /// </summary> public class NHibernateHelper { private ISessionFactory _sessionFactory; public NHibernateHelper() { _sessionFactory = GetSessionFactory(); } private ISessionFactory GetSessionFactory() { Configuration cfg = new Configuration(); ISessionFactory sf = cfg.Configure().BuildSessionFactory(); return sf; } public ISession GetSession() { ISession session = _sessionFactory.OpenSession(); return session; } }
以上就是创建个NHibernate的Session。 接下来是在Guestbook.IDal定义持久层相关的接口,首先是一个通用的增删改查接口,如下:
代码
/// <summary>
/// 数据执行类接口 /// </summary> /// <typeparam name="T"></typeparam> public interface IDbObject<T> { void Save(T entity); void Delete(T entity); void Update(T entity); T Load(int sysNo); IList<T> GetList(); }
定义基本的增删改查,是个泛型接口,这样实现它的类可以接收所有实本类,实现通用的方法。 接下来在Guestbook.Dal 定义一个 DbObject<T>基类,实现IDbObject<T>的增删改查方法,并做具体的实现,像下面这样:
代码
/// <summary>
/// 数据执行基础泛型类 /// </summary> /// <typeparam name="T"></typeparam> public class DbObject<T>:IDbObject<T> where T:class { private ISession _session; public DbObject() { NHibernateHelper nhbHelper = new NHibernateHelper(); _session = nhbHelper.GetSession(); } #region IDbObject<T> 成员 public void Save(T entity) { _session.Save(entity); _session.Flush(); } public void Delete(T entity) { _session.Delete(entity); _session.Flush(); } public void Update(T entity) { _session.Update(entity); _session.Flush(); } public T Load(int sysNo) { return _session.Load<T>(sysNo); } public IList<T> GetList() { return _session.CreateCriteria<T>().AddOrder(NHibernate.Criterion.Order.Asc("SysNo")).List<T>(); } #endregion
比如 Save(T entity) 方法,实现具体的_session.Save(entity);_session.Flush();方法。通过NHibernate操作数据库。接下来就可以具体的持久业务类继承这个操作基类了。下面以Guestbook 为原型做相关讲解。为了数据层解藕,先建接口IGuestbookDal如下:
代码
/// <summary>
/// 留言本数据操作接口 /// </summary> public interface IGuestbookDal { void Save(GuestbookInfo entity); void Delete(GuestbookInfo entity); void Update(GuestbookInfo entity); GuestbookInfo Load(int sysNo); IList<GuestbookInfo> GetList(); }
然后在Guestbook.Dal中建一个具体持久类,这个类继承DbObject<GuestbookInfo>基类并实现IGuestbookDal接口,代码如下:
/// <summary>
/// 留言本数据处理类 /// </summary> public class GuestbookDal:DbObject<GuestbookInfo>,IGuestbookDal { }
具体操作已经在泛型基类DbObject中实现了,所以这个类不用再实现什么操作即可。再加比如UserDal;ProductDal都可以直接继承不用实现就可以了。大大减少了很多工作量(之前园子里有觉得应该取消泛型,这么好的东西给我留着吧。阿们)。这样持久层基本就完成了。接下来说说业务类。
首先,一切为了解藕,一切为了面向接口。主阿,饶恕我吧。先在Guestbook.IBiz中定义个业务接口IGuestbookBiz吧:
代码
/// <summary>
/// 留言本业务接口 /// </summary> public interface IGuestbookBiz { void Save(GuestbookInfo entity); void Delete(GuestbookInfo entity); void Update(GuestbookInfo entity); GuestbookInfo Load(int sysNo); IList<GuestbookInfo> GetList(); }
这没啥说的了,再说大家都烦了。再紧跟着在Guestbook.Biz中建一个业务类GuestbookBiz 实现 以上接口:
代码
/// <summary>
/// 留言本业务类 /// </summary> public class GuestbookBiz:IGuestbookBiz { private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>("DalType"); #region IGuestbookBiz 成员 public void Save(GuestbookInfo entity) { _guestbookDal.Save(entity); } public void Delete(GuestbookInfo entity) { _guestbookDal.Delete(entity); } public void Update(GuestbookInfo entity) { _guestbookDal.Update(entity); } public GuestbookInfo Load(int sysNo) { return _guestbookDal.Load(sysNo); } public IList<GuestbookInfo> GetList() { return _guestbookDal.GetList(); } #endregion }
注意这句 private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>("DalType");,这里是业务层引用持久层,并不是直接New的,而是通过持久接口IGuestbookDal定义的,通过Unity加载进来的。这样就实现了相当成份的解藕了,不是由使用者去引用并实例被引用者,这个操作是由Ioc容器来做(这里是Unity)。这里用到了UnityHelper类了,它的写法如下(没有深入学习,只是基本操作):
代码
public static class UnityHelper
{ /// <summary> /// 通过Unity实组装对象泛型方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="entity"></param> /// <returns></returns> public static T UnityToT<T>(string name) { IUnityContainer container = CreateContainer(); T model = container.Resolve<T>(name); return model; } /// <summary> /// 通过Unity实组装对象泛型方法 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="entity"></param> /// <returns></returns> public static T UnityToT<T>() { IUnityContainer container = CreateContainer(); T model = container.Resolve<T>(); return model; } /// <summary> /// 通过配置创建UnityContainer /// </summary> /// <returns></returns> public static IUnityContainer CreateContainer() { IUnityContainer container = new UnityContainer(); UnityConfigurationSection section = (UnityConfigurationSection) System.Configuration.ConfigurationManager.GetSection("unity"); section.Containers["Guestbook"].Configure(container); return container; } }
CreateContainer就是创建UnityContainer,它是Unity的核心所在。通过它就可以进行动态组装了。这里可以用代码创建也可以通过配置文件。我选择配置文件。因为直接写代码里面侵入太强了,失去了很多灵活装配的意义。配置我直接写在了Web.config里面,也可以单独写配置文件。我们在后面讲一下配置文件。UnityToT(string name)是我写的一个泛型方法,通过name查找相应的配置项去组装并反回接口的对象,T是我们的接口。使用就如上面:private IGuestbookDal _guestbookDal = UnityHelper.UnityToT<IGuestbookDal>("DalType");,<IGuestbookDal>就是接口,我们在配置里面有指定。"DalType"就是配置的名称。下面我们看一下相关的配置项:
代码
<unity>
<containers> <container name="Guestbook"> <types> <type name="BizType" type="Guestbook.IBiz.IGuestbookBiz,Guestbook.IBiz" mapTo="Guestbook.Biz.GuestbookBiz,Guestbook.Biz"/> <type name="DalType" type="Guestbook.IDal.IGuestbookDal,Guestbook.IDal" mapTo="Guestbook.Dal.GuestbookDal,Guestbook.dal"/> </types> </container> </containers> </unity>
type节就是我们的对应配置项,name是我们前面泛型方法要传入的name,type为接口,mapTo为具体的业务类。比如上面的IGuestbookDal持久层接口对应的相应的GuestbookDal持久类,这样配置后Unity就会帮我们根据接口装配(实例化)实现类,并反回相应的实例对象,我们就可以通过这个对象实现具体业务了,比如:_dao.Save(entity);。
这样我们的业务层也完成了,接下来就是UI层调用业务层就可以了。UI层我们一样通过Unity进行装配,UI层只引用实体类Guestbook.Model和Guestbook.IBiz业务层接口(当然用Unity要引用相应的UnityHelper类了)。这样UI层对业务层向下层次全部是弱依赖。UI我们基于的ASP.NET Mvc,所以我们在Controllers的里面进行业务层的装配并使用。我们以GuestbookInfo的列表显示为例,说一下。相应的Action叫说GuestbookList,代码如下:
代码
private static IGuestbookBiz _biz = UnityHelper.UnityToT<IGuestbookBiz>("BizType");
public ActionResult GuestbookList() { IList<GuestbookInfo> guestbookList = _biz.GetList(); return View(guestbookList); }
private static IGuestbookBiz _biz = UnityHelper.UnityToT<IGuestbookBiz>("BizType");就是业务层装配了,我们通过业务接口IGuestbookBiz进行引用。通过_biz.GetList()就取得了相应的IList<GuestbookInfo>了。最后在相对应的View里面,指定Page Model ,像这样:Inherits="System.Web.Mvc.ViewPage<IList<Guestbook.Model.GuestbookInfo>>";然后在View中循环显示一下集合数据就可以了,大概像下面这样:
代码
<%foreach(var item in Model){ %>
<table width="500" border="0" cellpadding="0" cellspacing="0"> <tr> <th>姓名</th> <th style="background-color:White"><%=item.GuestName %></th> <th>性别</th> <th style="background-color:White"><%=item.Sex==1?"男":"女" %></th> </tr> <tr> <td colspan="4" height="50" valign="top"> <%=item.GuestMessage %> </td> </tr> <tr> <td colspan="4"><%=Html.ActionLink("删除","Delete",new{sysno=item.SysNo}) %></td> </tr> </table> <%} %>
最后放一张运行的图片,其它的Save,Delete方式其本相同,这里就不多讲了。大家可以在这里下载源码(已上传)。
|
请发表评论