依賴註入主要是一種結構性的模式,註重的是類與類之間的結構,它要達到的目的就是設計原則中最少知道和合成復用的原則,減少內部依賴,履行單一職責,最終就是強解耦。依賴註入目前最好的實現就是依賴註入容器。 Unity是微軟Patterns & Practices團隊所開發的一個輕量級的,並且可擴展的依賴註入 ...
- 簡介
依賴註入主要是一種結構性的模式,註重的是類與類之間的結構,它要達到的目的就是設計原則中最少知道和合成復用的原則,減少內部依賴,履行單一職責,最終就是強解耦。依賴註入目前最好的實現就是依賴註入容器。
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); }
運行測試結果達到工廠模式同樣的效果,並且可擴展性更強、項目解耦,減少項目依賴。
至此,項目介紹完畢,更多精彩,且聽下回分解!