在面向对象的设计中,依赖注入(IoC)作为一种重要的设计模式,主要用于削减计算机程序的耦合问题,相对于Java中的Spring框架来说,微软企业库中的Unity框架是目前.NET平台中运用比较广泛的依赖注入框架之一(还有的Spring.NET等)。但是对于这些“官方版本”的强大依赖注入框架,通常使用和配置都比较复杂,我个人更希望实现一种“约定胜于配置”轻量级IoC框架。

实现依赖注入主要是运用C#中的反射技术,通过配置文件,把代码的实现注入到接口中。用户只是访问接口,对于接口的实现一概不知,可以有效地对接口和实现进行解耦,在介绍代码之前,先来看一下我们的配置文件:

<appSettings>
        <!--依赖注入配置-->
        <add key="Domain.Entity.IRepository" value="Infrastructure.Repository"/>
</appSettings>

Domain.Entity.IRepository与Infrastructure.Repository都是.NET中的程序集(dll),其中Domain.Entity.IRepository中定义了领域模型中所需要的仓储接口,Infrastructure.Repository中定义了仓储接口的实现。领域模型需要访问数据的时候,并不是直接访问ADO或者ORM,而是通过访问Domain.Entity.IRepository中的仓储接口,再通过依赖注入把Infrastructure.Repository中的实现注入到接口中,这样就有效隔离了领域模型对数据实现的依赖,如果后期需要更换数据库或ORM框架,只需要实现另一个Infrastructure.Repository,并更新依赖注入配置即可。
    下面介绍轻量级依赖注入的实现方法,先贴代码:  

    public sealed class DependencyInjector
    {
        /// <summary>
        /// 根据名称和构造函数的参数加载相应的类
        /// </summary>
        /// <typeparam name="T">需要加载的类所实现的接口</typeparam>
        /// <param name="className">类的名称</param>
        /// <param name="args">构造函数的参数(默认为空)</param>
        /// <returns>类的接口</returns>
        public static T GetClass<T>(string className, object[] args = null) where T : class
        {
            //获取接口所在的命名空间
            string factoryName = typeof(T).Namespace;
            //通过依赖注入配置文件获取接口实现所在的命名空间
            string dllName = ConfigurationManager.AppSettings[factoryName];
            //获取类的全名
            string fullClassName = dllName + "." + className;
            //根据dll和类名,利用反射加载类
            object classObject = Assembly.Load(dllName).CreateInstance(fullClassName, true, BindingFlags.Default, null, args, null, null); ;
            return classObject as T;
        }
    }

代码中的typeof(T).Namespace,其中T是接口的类型,获取接口的命名空间以后,再通过我们的配置文件,就可以获取类的命名空间,再加上类名,通过c#的反射机制,就可以加载类的实现。也许你会说,我们只知道接口,并不知道类名是什么,别急,我们对该代码进一步进行封装:

    public sealed class IoC
    {
        /// <summary>
        /// //通过接口名称和构造函数的参数得到实现
        /// </summary>
        /// <typeparam name="T">接口类型</typeparam>
        /// <param name="args">构造函数的参数</param>
        /// <returns>接口的实现</returns>
        public static T Resolve<T>(object[] args = null) where T : class
        {
            //获取类名
            );
            //通过判断fullName中是否包含`符号来判断是否是泛型
            string fullName = typeof(T).FullName;
            int flag = fullName.IndexOf('`');
            //如果是泛型,需要特殊处理
            )
            {
                int dot = fullName.LastIndexOf('.', flag);
                //这里去掉方法名前面的点和I
                className = fullName.Substring(dot + );
            }
            return DependencyInjector.GetClass<T>(className, args);
        }
    }

在这里我们就用到了上面所说的”约定胜于配置“,我们约定接口的名称是在类名的前面加上I,并且接口和实现必须是独立的程序集。如果类名是Helper,那么接口的名字就必须是IHelper,我们通过去掉接口前面的I来获得实现的类名。如果是泛型接口,还需要进行特殊的处理,这里我们通过判断类型的全名中是否包含”`“符号来判断是否泛型接口。

下面举一个使用该依赖注入的例子:

     public static Book GetById(string bookID)
        {
            IRepository<Book> bookRep = IoC.Resolve<IRepository<Book>>();
            return bookRep.GetByKeys(bookID);
        }

        public int GetBookCount()
        {
            IBookRepository bookRep = IoC.Resolve<IBookRepository>();
            return bookRep.GetCount();
        }

在这里我们是不知道接口的实现的,通过我们封装的IoC.Resolve方法,可以把我们配置文件中的接口实现”注入到接口“中,通过这种解耦的方式,后期我可以更加灵活地对代码进行重构。

不用Unity库,自己实现.NET轻量级依赖注入的更多相关文章

  1. 不用Unity库,利用.NET动态代理自己实现AOP

    AOP意为面向切面的程序设计,主要表现为对不同的代码逻辑进行隔离,从而降低不同业务逻辑之间的耦合性,AOP又理解为“横切”,可以在不改变原有实现的情况下,对代码进行拦截和扩展,如果原有设计像一个瓶子, ...

  2. Unity轻量级依赖注入容器

    一.前言 Unity是一个轻量级的可扩展的依赖注入容器,支持构造函数,属性和方法调用注入.在Nuget里安装unity

  3. Unity文档阅读 第二章 依赖注入

    Introduction 介绍Chapter 1 outlines how you can address some of the most common requirements in enterp ...

  4. 【Unity】微软的一款依赖注入组件

    前言 前面学习了autofac这个依赖注入组件,本来是打算写在一起的,因为这个组件没打算像autofac一样详细的写,只是写下以前自己鼓捣玩搭建框架然后使用的一个依赖注入组件,并且也是进行了封装使用. ...

  5. 使用Unity解耦你的系统—PART3——依赖注入

    继续学习Unity,在前几篇中已经将Unity的使用方法做了一个还算详细的介绍了,主要是如何通过代码及配置文件来注册对象之间的关系.Unity内置所有的生命周期管理使用介绍,及Unity的Regist ...

  6. 使用Unity 实现ASP.NET Web API 依赖注入

    DI/IoC 的设计前面已经讲过好几次了,简单的一段话说明就是:「目标对象与外部相依的方式仅相依于 interface,而相依 interface 的 instance 透过 constructor ...

  7. 理解依赖注入(IOC)和学习Unity

    资料1: IOC:英文全称:Inversion of Control,中文名称:控制反转,它还有个名字叫依赖注入(Dependency Injection). 作用:将各层的对象以松耦合的方式组织在一 ...

  8. 依赖注入与Unity(一) 介绍

        在你学习依赖注入和Unity之前,你需要明白你为什么要使用它们.为了明白为什么要使用它们,你应该明白依赖注入和Unity能够帮助你解决什么类型的问题.作为介绍部分,这一章不会涉及太多关于Uni ...

  9. 通过Unity依赖注入

    前言 Unity容器的思想起始于我在为Web Client Sofitware Factory项目工作的时候,微软的patterns&practices团队已经使用依赖注入的概念好几年了在那时 ...

随机推荐

  1. 0c-33-@class,循环retain

    2个对象互相有着引用,A中有B,B中有A. // 对于循环retain的情况,对象不能够释放,此时只能让一方使用assign一方使用retain,retain用于对象assign用于基本类型,assi ...

  2. WPF 之 左键弹出操作菜单,并禁用右键菜单

    在目前的WPF版本中,很多的控件都有一个ContextMenu的属性,可以设置组件的右键菜单,这点确实是很方便,但是有些时候我们可能会需要当单击鼠标左键才弹出这个ContextMenu,而不是单击鼠标 ...

  3. 共享锁(S锁)和排它锁(X锁)

    1 什么叫数据库共享锁[S]锁和[X]锁 共享锁[S锁]    又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁.这保 ...

  4. 【Android车载系统 News | Tech 3】News 从手机征战到汽车 Android Auto对比CarPlay 2014-12-29

    Google和苹果都试图给用户的汽车带来一个安全和友好的移动体验.Android Auto和CarPlay是这两家公司推出的专为车载而重新设计的移动用户界面,双方目前都在筹备着在明年正式大规模推广. ...

  5. 接入淘宝API(PHP版本)

    本文链接! http://www.cnblogs.com/MicroHao/p/4030117.html 遇到的问题一: $req = new WaimaiOrderIndexGetRequest; ...

  6. html 中根据后台参数显示 相应的样式 EL表达式

    <li><a class="${return_product_statu==-1||return_product_statu==null?'switch_xz':'none ...

  7. jq使用手册

    jq 使用手册   翻译整理:Young.J 官方网站:http://jquery.com    jQuery是一款同prototype一样优秀js开发库类,特别是对css和XPath的支持,使我们写 ...

  8. Umbraco(7)-The Navigation Menu And A Parent Page with Infinite Children

    原文链接:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/umbraco7the-navigation-menu-and-a-par ...

  9. HDU 5253 连接的管道 (最小生成树)

    连接的管道 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submi ...

  10. hdu 4739 状压DP

    这里有状态压缩DP的好博文 题目:题目比较神,自己看题目吧 分析: 大概有两种思路: 1.dfs,判断正方形的话可以通过枚举对角线,大概每次减少4个三角形,加上一些小剪枝的话可以过. 2.状压DP,先 ...