C# IOC DI 学习

之前一直不理解IOC DI,今天使劲研究了下,感觉朦朦胧胧有点感觉了,网上的这篇文章对我的有很大的启发

http://www.cnblogs.com/jin-yuan/p/3823559.html

我仔细学习了后,按照自己的习惯从头到尾自己敲了个实例,感觉特高兴,除了用来理解IOC和DI思想,基本没考虑其他,但是还是贴出来分享一下吧

1,我们先实现一个简单的读取数据库的功能,由于懒得真的去读数据库了,直接模拟了,首先是一个简单的实体类User

namespace ConsoleApp1 {
    public class User {
        public int UserID { get; set; }
        public string UserName { get; set; }  
    }
}

2,然后模拟一个空的DBHelper,只是用来感受IOC的方便,没有真正实现效果,下面的类基本每个都定义了一个接口

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1 {
    public interface IDBHelper {
        int Execute(string sql);
    }
    /// <summary>
    /// 模拟的DBHelper
    /// </summary>
    public class DBHelper : IDBHelper {
        private ILogHelper logHelper;
        public DBHelper(ILogHelper logHelper) {
            this.logHelper = logHelper;
        }
        public int Execute(string sql) {
            logHelper.Info("执行sql:" + sql);
            return 1;
        }
    }
}

  3,DBHelper里面有个LogHelper只是一个输出类,加这个类,也是为了体验DI的便利性

using System;

namespace ConsoleApp1 {
    public interface ILogHelper {
        void Info(string msg);
    }
    public class LogHelper : ILogHelper {
        public void Info(string msg) {
            Console.WriteLine("info: " + msg);
        }
    }
}

  4,然后是模拟的数据访问类,里面用集合模拟的数据操作

using System.Collections.Generic;

namespace ConsoleApp1 {
    public interface IUserDAL {
        int Add(User user);
        List<User> GetUsers();
    }
    public class UserDAL : IUserDAL {
        private IDBHelper dbHelper;
        public UserDAL(IDBHelper dbHelper) {
            this.dbHelper = dbHelper;
        }
        public static List<User> users = new List<User>() {
            new User(){
                UserID = 1,
                UserName ="张三"
            },
            new User(){
                UserID =2,
                UserName ="李四"
            }
        };
        public int Add(User user) {
            dbHelper.Execute("insert into User (UserID,UserName) values (3,'王五')");
            users.Add(user);
            return 1;
        }
        public List<User> GetUsers() {
            return users;
        }
    }
}

  

5,然后是业务逻辑类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1 {
    public interface IUserBLL {
        int Add(User user);
        List<User> GetUsers();
    }
    public class UserBLL : IUserBLL {
        private IUserDAL userDAL;
        private ILogHelper logHelper;
        public UserBLL(IUserDAL userDAL, ILogHelper logHelper) {
            this.userDAL = userDAL;
            this.logHelper = logHelper;
        }
        public int Add(User user) {
            logHelper.Info("UserBLL.Add");
            return userDAL.Add(user);
        }
        public List<User> GetUsers() {
            logHelper.Info("UserBLL.GetUsers");
            return userDAL.GetUsers();
        }
    }
}

  6,模拟是实现的DI管理类,为了好理解,我按照最简单的方式实现的

using System;
using System.Collections.Generic;
using System.Reflection;

namespace ConsoleApp1 {
    /// <summary>
    /// 简单模拟的DI注入类
    /// </summary>
    public class DIManager {
        /// <summary>
        /// 存放关系的容器
        /// </summary>
        private Dictionary<Type, Type> container;
        public DIManager() {
            container = new Dictionary<Type, Type>();
        }
        /// <summary>
        /// 将接口和实现类关联绑定起来
        /// </summary> 
        public void Bind<K, V>() {
            container.Add(typeof(K), typeof(V));
        }
        /// <summary>
        /// 获取泛型类型的对象
        /// </summary> 
        public T Get<T>() {
            return (T)Injection(typeof(T));
        }
        /// <summary>
        /// 对传入的类型进行构造函数注入
        /// </summary> 
        private object Injection(Type type) {
            object instance = null;
            foreach (ConstructorInfo ci in type.GetConstructors()) {  //循环类的构造函数
                if (ci.GetParameters().Length > 0) {
                    List<object> parameters = new List<object>();
                    foreach (ParameterInfo pi in ci.GetParameters()) { //循环构造函数的参数
                        if (container.ContainsKey(pi.ParameterType)) {
                            parameters.Add(Injection(container[pi.ParameterType])); //递归实现所有相关注册过的类型的构造函数注入
                        }
                    }
                    instance = CreateInstance(type, parameters.ToArray());
                    break;
                }
            }
            if (instance == null) {
                instance = CreateInstance(type);
            }
            return instance;
        }
        /// <summary>
        /// 创建对象
        /// </summary> 
        private object CreateInstance(Type type, params object[] args) {
            return Activator.CreateInstance(type, args);
        }
    }
}

  7,最后是Program的使用

using System;

namespace ConsoleApp1 {
    class Program {
        static void Main(string[] args) {
            DIManager manager = new DIManager();
            manager.Bind<IUserBLL, UserBLL>();
            manager.Bind<IUserDAL, UserDAL>();
            manager.Bind<IDBHelper, DBHelper>();
            manager.Bind<ILogHelper, LogHelper>();
            IUserBLL userBLL = manager.Get<UserBLL>();
            User user = new User() { UserID = 3, UserName = "王五" };
            Console.WriteLine(userBLL.Add(user));
            foreach (var u in userBLL.GetUsers()) {
                Console.WriteLine(u.UserName);
            }
            Console.ReadKey();
        }
    }
}

  总结:IOC是控制反转,就是把底层的耦合抛到外面,代码里定义的那么多接口就是实现这个效果,但是即使我们把控制抛到了外面,这些对象还是得创建啊,所以就用到了DI(依赖注入)上面的类里面都是通过构造函数来获取我们要用到得对象,对象哪来的?答,注册接口和类得关系,然后在代码里自动生成,然后通过构造函数注入得,大概就是这么理解的了

猜你喜欢

转载自www.cnblogs.com/luludongxu/p/10672468.html