基于.net EF6 MVC5+WEB Api 的Web系统框架总结(3)-项目依赖注入
- 简介
依赖注入主要是一种结构性的模式,注重的是类与类之间的结构,它要达到的目的就是设计原则中最少知道和合成复用的原则,减少内部依赖,履行单一职责,最终就是强解耦。依赖注入目前最好的实现就是依赖注入容器。
unity是微软patterns & practices团队所开发的一个轻量级的,并且可扩展的依赖注入(dependency injection)容器,它支持常用的三种依赖注入方式:构造器注入(constructor injection)、属性注入(property injection),以及方法调用注入(method call injection).
本项目基于unity,减少内部依赖,实现项目解耦。基于lgpl协议开源。
2.项目源码
using microsoft.practices.unity; using microsoft.practices.unity.configuration; using system; using system.collections.generic; using system.configuration; using system.linq; using system.text; namespace shiquan.unity { /// <summary> /// unity 辅助对象 /// </summary> public class unityhelper { #region 单例 private static readonly unityhelper _instance = new unityhelper(); /// <summary> /// unity 辅助对象 /// </summary> public static unityhelper instance { get { return _instance; } } #endregion private readonly iunitycontainer _container = new unitycontainer(); /// <summary> /// 获取容器 /// </summary> public iunitycontainer container { get { return _container; } } private unityhelper() { var configuration = configurationmanager.getsection(unityconfigurationsection.sectionname) as unityconfigurationsection; if (configuration != null) { configuration.configure(_container); } } #region 获取对应接口的具体实现类 /// <summary> /// 获取实现类(默认映射) /// </summary> /// <typeparam name="t">接口类型</typeparam> /// <returns>接口</returns> public t getresolve<t>() { return _container.resolve<t>(); } /// <summary> /// 获取实现类(默认映射)带参数的 /// </summary> /// <typeparam name="t">接口类型</typeparam> /// <param name="parameter">参数</param> /// <returns>接口</returns> public t getresolve<t>(params parameteroverride[] parameter) { return _container.resolve<t>(parameter); } /// <summary> /// 获取实现类(指定映射)带参数的 /// </summary> /// <typeparam name="t"></typeparam> /// <param name="name"></param> /// <param name="parameter"></param> /// <returns>接口</returns> public t getresolve<t>(string name, params parameteroverride[] parameter) { return _container.resolve<t>(name, parameter); } #endregion #region 判断接口是否被注册了 /// <summary> /// 判断接口是否被实现了 /// </summary> /// <typeparam name="t">接口类型</typeparam> /// <returns>bool</returns> public bool isregistered<t>() { return _container.isregistered<t>(); } /// <summary> /// 判断接口是否被实现了 /// </summary> /// <typeparam name="t">接口类型</typeparam> /// <param name="name">映射名称</param> /// <returns></returns> public bool isregistered<t>(string name) { return _container.isregistered<t>(name); } #endregion } }
源码地址:https://gitee.com/shiquan25/shiquan.unity
3.调用示例
下面演示调用此程序示例:
首先我们创建数据操作基础项目,定义idatabase接口,定义一获取名称的方法。
using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace shiquan.dataaccess { /// <summary> /// 定义接口 /// </summary> public interface idatabase { string name { get; } } }
创建sqlserver项目,定义sqldatabase实现idatabase接口。
using shiquan.dataaccess; using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace shiquan.dataserver { /// <summary> /// 实现 /// </summary> public class sqldatabase : idatabase { public string name { get { return "sqldatabase"; } } } }
创建mysql 项目,定义mysqldatabase实现idatabase接口。
using shiquan.dataaccess; using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace shiquan.datamysql { /// <summary> /// 实现 /// </summary> public class mysqldatabase : idatabase { public string name { get { return "mysqldatabase"; } } } }
创建数据操作工厂项目,定义datafactory实现根据参数调用不同的实现类。
using shiquan.dataaccess; using shiquan.datamysql; using shiquan.dataserver; using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; namespace shiquan.datarepository { /// <summary> /// 数据工厂 /// </summary> public class datafactory { /// <summary> /// 获取数据操作对象 /// </summary> /// <param name="name"></param> /// <returns></returns> public static idatabase getdatabase(string name) { switch (name) { case "mysql": { return new mysqldatabase(); } case "sqlserver": default: { return new sqldatabase(); } } } } }
创建console程序进行测试
using shiquan.dataserver; using shiquan.datamysql; using shiquan.unity; using system; using system.collections.generic; using system.linq; using system.text; using system.threading.tasks; using shiquan.dataaccess; using shiquan.datarepository; namespace consoleapp { class program { static void main(string[] args) { console.writeline("实例并调用sql server..."); idatabase sqlserver = datafactory.getdatabase("sqlserver"); console.writeline(sqlserver.name); console.writeline("实例并调用mysql..."); idatabase mysql = datafactory.getdatabase("mysql"); console.writeline(mysql.name); console.readline(); } } }
项目结构大概是这样的:
运行结果:
4.unity调用
假设此时,如果我们需要实现其他数据库操作,实现idatabase接口时,除了增加其他数据库操作项目,还得修改、调整数据操作工厂项目。
但是如果我们的数据操作工厂项目改用依赖注入的方式,工厂项目是不需要引用sqlserver项目、mysql项目及其他数据库操作项目,可以不改动工厂项目的情况下,主程序直接在配置文件中添加相应的操作项目及类,以达到面向接口开发、减少内部依赖、实现项目解耦。
项目添加程序包
主程序配置文件(app.config或web.config)增加配置
<configsections> <section name="unity" type="microsoft.practices.unity.configuration.unityconfigurationsection,microsoft.practices.unity.configuration" /> </configsections>
配置接口,接口实现对象
<unity> <typealiases> <typealias alias="idatabase" type="shiquan.dataaccess.idatabase,shiquan.dataaccess" /> <typealias alias="sqlserver" type="shiquan.dataserver.sqldatabase,shiquan.dataserver" /> <typealias alias="mysql" type="shiquan.datamysql.mysqldatabase,shiquan.datamysql" /> </typealiases> <containers> <container> <type type="idatabase" mapto="sqlserver" name="sqlserver"></type > <type type="idatabase" mapto="mysql" name="mysql"></type > </container> </containers> </unity>
工厂项目实例调用
/// <summary> /// 获取数据操作对象 /// </summary> /// <param name="name"></param> /// <returns></returns> public static idatabase getdatabase(string name) { //switch (name) //{ // case "mysql": // { // return new mysqldatabase(); // } // case "sqlserver": // default: // { // return new sqldatabase(); // } //} return shiquan.unity.unityhelper.instance.getresolve<idatabase>(name); }
运行测试结果达到工厂模式同样的效果,并且可扩展性更强、项目解耦,减少项目依赖。
至此,项目介绍完毕,更多精彩,且听下回分解!