分享

使用Microsoft.Practices.Unity 依赖注入

 ThinkTank_引擎 2016-11-21

    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 的基本用法介绍。

   

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多