使用Microsoft.Practices.Unity 依賴注入


    Unity是微軟Patterns & Practices團隊所開發的一個輕量級的,並且可擴展的依賴注入(Dependency Injection)容器,它支持常用的三種依賴注入方式:構造器注入(Constructor Injection)、屬性注入(Property Injection),以及方法調用注入(Method Call Injection).

    假設我們有下面的場景代碼,在代碼里面有一個很簡單的customer對象,customer 對象有個save 方法, 這個方法通過調用ICustomerDataAccess.Save將數據持久到數據庫中, 在列子中我們實現了dataaccess的sql版本和mysql版本,也就是說我們這個customer對象,可以支持持久化到sql server 或 mysql.

       

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;

namespace UnitySample
{
    public interface ICustomerDataAccess
    {
        void Save(Customer c);
    }

    public class CustomerSqlDataAccess : ICustomerDataAccess
    {
        public void Save(Customer c)
        {
            Console.Write("{2}, save data id:{0},name{1}",c.Id,c.Name,this.GetType().ToString());
        }
    }

    public class CustomerMysqlDataAccess : ICustomerDataAccess
    {
        public void Save(Customer c)
        {
            Console.Write("{2}, save data id:{0},name{1}", c.Id, c.Name, this.GetType().ToString());
        }
    }

    public class Customer
    {
        public ICustomerDataAccess CustomerDataAccess { get; set; }

        public string Id { get; set; }
        public string Name { get; set; }

        public void Save()
        {
            CustomerDataAccess.Save(this);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {

        }
    }
}

 

傳統做法可能是在配置文件中填幾個一個變量 dbType = sql  or my sql. 然后在customer 對象中根據設定的db type 來實力化不同的dataaccess.

   代碼可能會是下面這個樣子,這樣的話,customer 對象實際上依賴於CustomerSqlDataAccess 和 CustomerSqlDataAccess 的,而且,未來比如要新增加其他數據庫的支持,則必須修改customer 對象的源代碼。

 

 public Customer()
 {
            if (DbType = "sql") { CustomerDataAccess = new CustomerSqlDataAccess(); } else { CustomerDataAccess = new CustomerSqlDataAccess(); } }

下面我們使用unity 來解除customer 對象對  CustomerSqlDataAccess 和 CustomerSqlDataAccess 的依賴。

一、 屬性注入(Property Injection)

    1.  配置unity

     為了以后調用方便,我這里建立了一個靜態方法,然后注入了兩個dataaccess。

 public class UnitySetup
    {
        public static void Config()
        {
            var container = new UnityContainer();
            container.RegisterType<ICustomerDataAccess, CustomerSqlDataAccess>();
            container.RegisterType<ICustomerDataAccess, CustomerSqlDataAccess>("mysql");
        }
    }

  然后我們需要在Main函數中調用這個方法配置unity containter.

  

     static void Main(string[] args)
        {
            UnitySetup.Config();
        }

 

    2. 標記屬性注入

   這步很簡單,直接在customer 類中的ICustomerDataAccess 定義上面添加[Dependency]標注即可。

      

[Dependency]
public ICustomerDataAccess CustomerDataAccess { get; set; }

 

    3. 通過resove 獲取對象

 

            var container = new UnityContainer();
            UnitySetup.Config(container);
            var sqlCustomer = container.Resolve<ICustomerDataAccess>();
            var mysqlCustomer = container.Resolve<ICustomerDataAccess>("mysql");

上面的代碼就分別獲取了CustomerSqlDataAccess 實例和CustomerSqlDataAccess實例

二 、構造器注入(Constructor Injection)

  1.  配置unity

    

  unityContainer.RegisterType<Customer>(
                new InjectionConstructor(new ResolvedParameter<ICustomerDataAccess>()));
            unityContainer.RegisterType<Customer>("mysqlCustomer",
                new InjectionConstructor(new ResolvedParameter<ICustomerDataAccess>("mysql")));

添加兩行注冊customer 對想到container.

 

2. 獲取

 var sqlCustomer = container.Resolve<Customer>(); var myqlCustomer = container.Resolve<Customer>("mysqlCustomer");

完整代碼如下
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;

namespace UnitySample
{
    
    public interface ICustomerDataAccess
    {
        void Save(Customer c);
    }

    public class CustomerSqlDataAccess : ICustomerDataAccess
    {
        public void Save(Customer c)
        {
            Console.WriteLine("{2}, save data id:{0},name{1}",c.Id,c.Name,this.GetType().ToString());
        }
    }

    public class CustomerMysqlDataAccess : ICustomerDataAccess
    {
        public void Save(Customer c)
        {
            Console.WriteLine("{2}, save data id:{0},name{1}", c.Id, c.Name, this.GetType().ToString());
        }
    }

    public class UnitySetup
    {
        public static void Config(IUnityContainer unityContainer)
        {
            unityContainer.RegisterType<ICustomerDataAccess, CustomerSqlDataAccess>();
            unityContainer.RegisterType<ICustomerDataAccess, CustomerMysqlDataAccess>("mysql");
            unityContainer.RegisterType<Customer>(
                new InjectionConstructor(new ResolvedParameter<ICustomerDataAccess>()));
            unityContainer.RegisterType<Customer>("mysqlCustomer",
                new InjectionConstructor(new ResolvedParameter<ICustomerDataAccess>("mysql")));
        }
    }

    public class Customer
    {
        private ICustomerDataAccess CustomerDataAccess { get; set;}

        public string Id { get; set; }
        public string Name { get; set; }

        public Customer(ICustomerDataAccess customerDataAccess)
        {
            CustomerDataAccess = customerDataAccess;
        }
        public void Save()
        {
            CustomerDataAccess.Save(this);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer();
            UnitySetup.Config(container);
            var sqlCustomer = container.Resolve<Customer>();
            var myqlCustomer = container.Resolve<Customer>("mysqlCustomer");

            sqlCustomer.Save();
            myqlCustomer.Save();
            
            Console.ReadKey();
        }
    }
}

三 、 方法調用注入(Method Call Injection)

 方法調用注入和輸入注入有點類似,只需要在調用的方法上面添加[InjectionMethod] 標注即可

  1.  配置unity

    

 unityContainer.RegisterType<Customer>("mysqlCustomer", new InjectionMethod("SetDataAccess", new ResolvedParameter<ICustomerDataAccess>("mysql")));

 

2. 獲取

 var sqlCustomer = container.Resolve<Customer>();
 var myqlCustomer = container.Resolve<Customer>("mysqlCustomer");

 完成后的代碼如下

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Practices.Unity;

namespace UnitySample
{
    
    public interface ICustomerDataAccess
    {
        void Save(Customer c);
    }

    public class CustomerSqlDataAccess : ICustomerDataAccess
    {
        public void Save(Customer c)
        {
            Console.WriteLine("{2}, save data id:{0},name{1}",c.Id,c.Name,this.GetType().ToString());
        }
    }

    public class CustomerMysqlDataAccess : ICustomerDataAccess
    {
        public void Save(Customer c)
        {
            Console.WriteLine("{2}, save data id:{0},name{1}", c.Id, c.Name, this.GetType().ToString());
        }
    }

    public class UnitySetup
    {
        public static void Config(IUnityContainer unityContainer)
        {
            unityContainer.RegisterType<ICustomerDataAccess, CustomerSqlDataAccess>();
            unityContainer.RegisterType<ICustomerDataAccess, CustomerMysqlDataAccess>("mysql");
            
            unityContainer.RegisterType<Customer>("mysqlCustomer",
                new InjectionMethod("SetDataAccess", new ResolvedParameter<ICustomerDataAccess>("mysql")));
        }
    }

    public class Customer
    {
        private ICustomerDataAccess CustomerDataAccess { get; set;}
        public string Id { get; set; }
        public string Name { get; set; }
      
        public void Save()
        {
            CustomerDataAccess.Save(this);
        }

        [InjectionMethod]
        public void SetDataAccess(ICustomerDataAccess dataAccess)
        {
            CustomerDataAccess = dataAccess;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var container = new UnityContainer();
            UnitySetup.Config(container);
            var sqlCustomer = container.Resolve<Customer>();
            var mysqlCustomer = container.Resolve<Customer>("mysqlCustomer");
            sqlCustomer.Save();
            mysqlCustomer.Save();
            Console.ReadKey();
        }
    }
}

好了,通過使用unity 依賴注入,customer 對象不再依賴具體的CustomerSqlDataAccess 和 CustomerMysqlDataAccess., 只依賴於接口ICustomerDataAccess。

上面就是unity 的基本用法介紹。

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM