C# Ioc、DI、Unity、TDD的一点想法和实践

catzhou 2018-05-17 原文

C# Ioc、DI、Unity、TDD的一点想法和实践

面向对象设计(OOD)有助于我们开发出高性能、易扩展以及易复用的程序。其中,OOD有一个重要的思想那就是依赖倒置原则(DIP)。

依赖倒置原则(DIP):一种软件架构设计的原则(抽象概念)

控制反转(IoC):一种反转流、依赖和接口的方式(DIP的具体实现方式)

依赖注入(DI):IoC的一种实现方式,用来反转依赖(IoC的具体实现方式)

IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)、

Unity:是微软推出的IOC框架

TDD:测试驱动开发,是敏捷开发中的一项核心实践和技术,也是一种设计方法论

 

上面的内容都是抄的(英文不好,放在这里备查),相关的内容看了一些,不明觉厉。

 

曾经写了一个酒店读写房卡的程序,不同的酒店门锁是不一样的,同一个酒店也有可能更换门锁,程序流程:

1.通过Api获取当前酒店的门锁类型

2.如果需要则下载对应门锁的dll

3.实现读写功能

一、定义接口

新建一个类库(Lock.Interface),代码如下:

namespace Lock
{
    public interface ILock
    {
        /// <summary>
        /// 门锁初始化
        /// </summary>
        /// <param name="password">初始化密码</param>
        /// <returns></returns>
        bool Init(int password);

    }
}

是不是算是IoC了?(我不确定)

二、单元测试

新建一个单元测试项目(Lock.Tests),代码如下:

1.门锁A单元测试

    /// <summary>
    /// 门锁A测试
    /// </summary>
    [TestClass()]
    public class LockATests
    {
        /// <summary>
        /// 初始化,password为正奇数
        /// </summary>
        [TestMethod()]
        public void InitTest()
        {
            ILock l = new LockA();
            var ret = l.Init(1);
            Assert.AreEqual(ret, true);
            ret = l.Init(2);
            Assert.AreEqual(ret, false);
            ret = l.Init(-1);
            Assert.AreEqual(ret, false);
        }

    }

2.门锁B单元测试

    /// <summary>
    /// 门锁B测试
    /// </summary>
    [TestClass()]
    public class LockBTests
    {
        /// <summary>
        /// 初始化测试,password为正偶数
        /// </summary>
        [TestMethod()]
        public void InitTest()
        {
            ILock l = new LockB();
            var ret = l.Init(1);
            Assert.AreEqual(ret, false);
            ret = l.Init(2);
            Assert.AreEqual(ret, true);
            ret = l.Init(-1);
            Assert.AreEqual(ret, false);
        }

显然编译都不能通过(不能通过编译也是一种测试)

三、定义类

 1.创建门锁A类库(Lock.LockA),代码如下:

    /// <summary>
    /// 门锁A
    /// </summary>
    public class LockA : ILock
    {
        
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="password">正确密码是正奇数</param>
        /// <returns></returns>
        public bool Init(int password)
        {
            return password > 0 && (password % 2) == 1;
        }
    }

2.创建门锁B类库(Lock.LockB),代码如下:

    /// <summary>
    /// 门锁B
    /// </summary>
    public class LockB : ILock
    {
        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="password">正确密码是正偶数</param>
        /// <returns></returns>
        public bool Init(int password)
        {
            return password > 0 && (password % 2) == 0;
        }
    }

分别编译成功后,回到测试项目,添加引用,编译通过,运行测试:

算不算TDD?

四、主程序

1.添加控制台项目

2.添加Unity(5.8.6)包

3.修改App.Config为:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,Unity.Configuration, Version=5.2.1.0, Culture=neutral, PublicKeyToken=6d32ff45e0ccc69f" />
    <!--上一些的内容网上复制过来有错误,后来查看UnityConfigurationSection的定义,复制了对应的程序集
    type="命名空间.类名,程序集"
    -->
  </configSections>
  <unity>
    <containers>
      <container name="LockA">
        <register type="Lock.ILock,Lock.Interface"  mapTo="Lock.LockA,Lock.LockA" ></register>
      </container>
      <container name="LockB">
        <register type="Lock.ILock,Lock.Interface"  mapTo="Lock.LockB,Lock.LockB"></register>
      </container>
    </containers>
  </unity>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
</configuration>

4.引用接口

5.Main方法如下:

        static void Main(string[] args)
        {
            var container = new UnityContainer();
            UnityConfigurationSection config = (UnityConfigurationSection)ConfigurationManager.GetSection(UnityConfigurationSection.SectionName);
            config.Configure(container, "LockA");
ILock l = container.Resolve<ILock>(); Console.WriteLine(l.Init(2)); Console.WriteLine(l.Init(1)); Console.WriteLine(l.Init(-1));
Console.ReadKey(); }

6.复制门锁A的dll复制到运行目录

7.运行结果如为:False、True、False,是门锁A的结果

8.将“LockA”改成“LockB”,并将门锁B的dll复制到运行目录,运行结果为True、False、False是门锁B的结果

算DI吧?咱都用了Unity了。

 

至此,基本实现了想要的功能,未来新酒店要增加门锁C、门锁D都没问题,只有老酒店改成门锁E的问题没解决(估计可以通过动态修改config文件实现,也不知道有没有更好地办法)。

 

发表于 2018-05-17 00:36 毛毛虫 阅读() 评论() 编辑 收藏

 

版权声明:本文为catzhou原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/catzhou/p/9048966.html

C# Ioc、DI、Unity、TDD的一点想法和实践的更多相关文章

  1. ArrayPool 源码解读之 byte[] 也能池化?

    一:背景 1. 讲故事 最近在分析一个 dump 的过程中发现其在 gen2 和 LOH 上有不少size较大 […]...

  2. C# 自动按键工具 – PHP-张工

    可以说是个简易版的按键精灵。 主要功能有:自动输入,截屏,控制鼠标移动点击。 自动按键工具主要使用 SendK […]...

  3. 寻找DevExpress破解经历之旅

    众所周知DevExpress是收费的,但是破解版的也不少,近期公司需要做发票套打的功能让我找个打印工具,我寻思 […]...

  4. WebAPI的AuthorizeAttribute扩展类中获取POST提交的数据

    在WEBAPI中,AuthorizeAttribute类重写时,如何获取post数据是个难题,网上找资料也不好 […]...

  5. 死磕Spring之IoC篇 – Bean 的属性填充阶段

    该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源 […]...

  6. C++模板沉思录

    0 论抽象——前言 故事要从一个看起来非常简单的功能开始: 请计算两个数的和。 如果你对Python很熟悉,你 […]...

  7. C# 扩展TaskScheduler实现独立线程池,支持多任务批量处理,互不干扰,无缝兼容Task

        为什么编写TaskSchedulerEx类?     因为.NET默认线程池只有一个线程池,如果某个批 […]...

  8. C# 9 新特性 —— 增强的 foreach

    增加的 foreach C# 9 新特性 —— 增强的 foreach Intro 在 C# 9 中增强了 f […]...

随机推荐

  1. MongoDb进阶实践之九 Mongodb的备份与还原

    一、引言       前几天写了MongoDB数据库的聚合。一说到“聚合”,用过关系型数据库的人都应该知道它是 […]...

  2. Map端数据倾斜

    Map端数据倾斜 MapReduce任务的数据倾斜一般指的是Reduce端数据倾斜,Map端怎么还会出现数据倾 […]...

  3. rational rose 2003完整汉化版 win7版

    下载链接:https://pan.baidu.com/s/1InpgNS_1-Rigw4fE3OX1Eg 软件 […]...

  4. 设计模式-观察者模式

    1、定义   定义对象的一种一对多/一的依赖关系。当一个对象的状态发生改变时,所有依赖它的对象都得到通知并被自 […]...

  5. ubuntu下的google拼音输入法(终结版)

    声明:此文章是从我的51cto博客上搬至于此. Ubuntu下SCIM应该是最好的中文输入法了,它与搜狗差不多 […]...

  6. Can\’t connect to MySQL server (10060)

    前天刚装的MySql,今天再次使用就出现了标题显示的错误。我是本地机器连接Linux下的MySql。 网上有一 […]...

  7. 架构设计之NodeJS操作消息队列RabbitMQ – 吴空

    架构设计之NodeJS操作消息队列RabbitMQ 一. 什么是消息队列? 消息(Message)是指在应用间 […]...

  8. 呼叫中心系统如何实现智能化办公

      呼叫中心系统如何实现智能化办公   八百呼呼叫中心系统提供企业呼叫中心专业解决方案,下面从八百呼呼叫中心系 […]...

展开目录

目录导航