zoukankan      html  css  js  c++  java
  • ASP.NET Mvc + NHibernate + Unity Application Block 示例程序

    今天无意间看到了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方式其本相同,这里就不多讲了。大家可以在这里下载源码(已上传)。

     

  • 相关阅读:
    LeetCode 189. Rotate Array
    LeetCode 965. Univalued Binary Tree
    LeetCode 111. Minimum Depth of Binary Tree
    LeetCode 104. Maximum Depth of Binary Tree
    Windows下MySQL的安装与配置
    LeetCode 58. Length of Last Word
    LeetCode 41. First Missing Positive
    LeetCode 283. Move Zeroes
    《蚂蚁金服11.11:支付宝和蚂蚁花呗的技术架构及实践》读后感
    删除docker下的镜像
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/1866704.html
Copyright © 2011-2022 走看看