zoukankan      html  css  js  c++  java
  • IoC实践--用Unity实现MVC5.0的IoC控制反转方法

        在MVC中,控制器依赖于模型对数据进行处理,也可以说执行业务逻辑。我们可以使用依赖注入(DI)在控制层分离模型层,这边要用到Repository模式,在领域驱动设计(DDD)中,Repository翻译为仓储,顾名思义,就是储存东西的仓库,可以理解为一种用来封装存储,读取和查找行为的机制,它模拟了一个对象集合。使用依赖注入(DI)就是对Repository进行管理,用于解决它与控制器之间耦合度问题,下面我们一步一步做一个简单示例。

    安装Unity

      首先我们需要新建一个UnityMVCDemo项目(ASP.NET MVC4.0),选择工具-库程序包管理器-程序包管理控制台,输入“Install-Package Unity.Mvc4”命令,VS2010可能需要先安装NuGet。

      或者通过工具-库程序包管理器-管理解决方案的 NuGet 程序包,通过联机搜索“Unity.Mvc4”进行安装。

      在安装过程中可能会遇到下面这样错误:

      根据异常信息,可以肯定是项目的.net framework版本无法安装Unity,这种安装VS会自动搜索Unity最新版本,但是最新版本往往有. net framework版本要求,不知道有没有指定Unity版本安装,可以看到我们安装的是Unity3.0版本,修改一下项目. net framework的版本为4.5,重新安装就可以了。

      安装Unity成功后,我们发现项目中多了“Microsoft.Practices.Unity”和“Microsoft.Practices.Unity.Configuration”两个引用,还有一个Bootstrapper类文件,Bootstrapper翻译为引导程序,也就是Ioc容器。

    复制代码
     1     public static class Bootstrapper
     2     {
     3         public static IUnityContainer Initialise()
     4         {
     5             var container = BuildUnityContainer();
     6 
     7             DependencyResolver.SetResolver(new UnityDependencyResolver(container));
     8 
     9             return container;
    10         }
    11 
    12         private static IUnityContainer BuildUnityContainer()
    13         {
    14             var container = new UnityContainer();
    15 
    16             // register all your components with the container here
    17             // it is NOT necessary to register your controllers
    18 
    19             // e.g. container.RegisterType<ITestService, TestService>();    
    20             RegisterTypes(container);
    21 
    22             return container;
    23         }
    24 
    25         public static void RegisterTypes(IUnityContainer container)
    26         {
    27 
    28         }
    29     }
    复制代码

    添加服务层

      首先我们添加一个Article实体类:

    复制代码
     1     /// <summary>
     2     /// Article实体类
     3     /// </summary>
     4     public class Article
     5     {
     6         public int Id { get; set; }
     7         public string Title { get; set; }
     8         public string Author { get; set; }
     9         public string Content { get; set; }
    10         public DateTime CreateTime { get; set; }
    11     }
    复制代码

      一般Repository都有一些相似的操作,比如增删改查,我们可以把它抽象为IArticleRepository接口,这样控制器依赖于抽象接口,而不依赖于具体实现Repository类,符合依赖倒置原则,我们才可以使用Unity进行依赖注入。

    复制代码
     1     /// <summary>
     2     /// IArticleRepository接口
     3     /// </summary>
     4     public interface IArticleRepository
     5     {
     6         IEnumerable<Article> GetAll();
     7         Article Get(int id);
     8         Article Add(Article item);
     9         bool Update(Article item);
    10         bool Delete(int id);
    11     }
    复制代码

      创建ArticleRepository,依赖于IArticleRepository接口,实现基本操作。

    复制代码
     1     public class ArticleRepository : IArticleRepository
     2     {
     3         private List<Article> Articles = new List<Article>();
     4 
     5         public ArticleRepository()
     6         {
     7             //添加演示数据
     8             Add(new Article { Id = 1, Title = "UnityMVCDemo1", Content = "UnityMVCDemo", Author = "xishuai", CreateTime = DateTime.Now });
     9             Add(new Article { Id = 2, Title = "UnityMVCDemo2", Content = "UnityMVCDemo", Author = "xishuai", CreateTime = DateTime.Now });
    10             Add(new Article { Id = 3, Title = "UnityMVCDemo2", Content = "UnityMVCDemo", Author = "xishuai", CreateTime = DateTime.Now });
    11         }
    12         /// <summary>
    13         /// 获取全部文章
    14         /// </summary>
    15         /// <returns></returns>
    16         public IEnumerable GetAll()
    17         {
    18             return Articles;
    19         }
    20         /// <summary>
    21         /// 通过ID获取文章
    22         /// </summary>
    23         /// <param name="id"></param>
    24         /// <returns></returns>
    25         public Article Get(int id)
    26         {
    27             return Articles.Find(p => p.Id == id);
    28         }
    29         /// <summary>
    30         /// 添加文章
    31         /// </summary>
    32         /// <param name="item"></param>
    33         /// <returns></returns>
    34         public Article Add(Article item)
    35         {
    36             if (item == null)
    37             {
    38                 throw new ArgumentNullException("item");
    39             }
    40             Articles.Add(item);
    41             return item;
    42         }
    43         /// <summary>
    44         /// 更新文章
    45         /// </summary>
    46         /// <param name="item"></param>
    47         /// <returns></returns>
    48         public bool Update(Article item)
    49         {
    50             if (item == null)
    51             {
    52                 throw new ArgumentNullException("item");
    53             }
    54 
    55             int index = Articles.FindIndex(p => p.Id == item.Id);
    56             if (index == -1)
    57             {
    58                 return false;
    59             }
    60             Articles.RemoveAt(index);
    61             Articles.Add(item);
    62             return true;
    63         }
    64         /// <summary>
    65         /// 删除文章
    66         /// </summary>
    67         /// <param name="id"></param>
    68         /// <returns></returns>
    69         public bool Delete(int id)
    70         {
    71             Articles.RemoveAll(p => p.Id == id);
    72             return true;
    73         }
    74     }
    复制代码

    IArticleRepository类型映射

      上面工作做好后,我们需要在Bootstrapper中的BuildUnityContainer方法添加此类型映射。

    复制代码
     1         private static IUnityContainer BuildUnityContainer()
     2         {
     3             var container = new UnityContainer();
     4 
     5             // register all your components with the container here
     6             // it is NOT necessary to register your controllers
     7 
     8             container.RegisterType<IArticleRepository, ArticleRepository>();
     9 
    10             // e.g. container.RegisterType<ITestService, TestService>();    
    11             RegisterTypes(container);
    12 
    13             return container;
    14         }
    复制代码

      我们还可以在配置文件中添加类型映射,UnityContainer根据配置信息,自动注册相关类型,这样我们就只要改配置文件了,当然推荐是这种方法,配置文件:

    复制代码
     1   <configSections>
     2     <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
     3              Microsoft.Practices.Unity.Configuration" />
     4   </configSections>
     5   <unity>
     6     <containers>
     7       <container name="defaultContainer">
     8         <register type="UnityMVCDemo.Models.IArticleRepository, UnityMVCDemo" mapTo="UnityMVCDemo.Models.ArticleRepository, UnityMVCDemo"/>
     9       </container>
    10     </containers>
    11   </unity>
    复制代码

      注意configSections节点要放在configuration节点下的第一个节点,关于Unity的配置文件配置参照http://www.cnblogs.com/xishuai/p/3670292.html,加载配置文件代码:

    1     UnityConfigurationSection configuration = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
    2     configuration.Configure(container, "defaultContainer");

      上面这段代码替换掉上面使用的RegisterType方法。

    服务注入到控制器

      在ArticleController中我们使用是构造器注入方式,当然还有属性注入和方法注入,可以看到ArticleController依赖于抽象IArticleRepository接口,而并不是依赖于ArticleRepository具体实现类。

    复制代码
     1     public class ArticleController : Controller
     2     {
     3         readonly IArticleRepository repository;
     4         //构造器注入
     5         public ArticleController(IArticleRepository repository)
     6         {
     7             this.repository = repository;
     8         }
     9 
    10         public ActionResult Index()
    11         {
    12             var data = repository.GetAll();
    13             return View(data);
    14         }
    15     }
    复制代码

    Global.asax初始化

      做完上面的工作后,我们需要在Global.asax中的Application_Start方法添加依赖注入初始化。

    复制代码
     1     // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
     2     // visit http://go.microsoft.com/?LinkId=9394801
     3     public class MvcApplication : System.Web.HttpApplication
     4     {
     5         protected void Application_Start()
     6         {
     7             AreaRegistration.RegisterAllAreas();
     8 
     9             WebApiConfig.Register(GlobalConfiguration.Configuration);
    10             FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    11             RouteConfig.RegisterRoutes(RouteTable.Routes);
    12 
    13             Bootstrapper.Initialise();
    14         }
    15     }
    复制代码

    后记

      示例代码下载:http://files.cnblogs.com/files/sexintercourse/UnityMVCDemo.rar

    后来经过了一系列的改进,我们后来的代码。

     代码下载http://files.cnblogs.com/files/sexintercourse/UnityMVCDemo20.zip

  • 相关阅读:
    功能3 -- 基于jquery的load()实现多个.html静态页,引用同一个header.html和footer.html文件
    功能2 -- hover出现遮照效果
    功能1 -- 顶部导航栏和返回顶部效果
    使用swiper简单的h5下滑翻页效果,
    Vue源码阅读,如何渲染代码块生成? 本文详解
    这15道Vue常见面试题,你会几道??
    学会这些Vue小技巧,可以早点下班和女神约会了!
    TypeScript在Model中是如何操作运用的?本文详解
    Vue3教程,抢先学习
    Webpack 5模块联邦会不会引发微前端的革命呢? 本文详解
  • 原文地址:https://www.cnblogs.com/sexintercourse/p/6147802.html
Copyright © 2011-2022 走看看