从零开始写C# MVC框架之--- 用autofac ioc 容器实现依赖注入
来源:互联网 发布:网络重口君 编辑:程序博客网 时间:2024/05/20 13:19
本章查找了一篇对依赖注入解释得非常不错的文章为基础,再加上自己的理解,不然还真不好用语言的方式表达清楚,引用下面这位仁兄的文章
CodingLabs 张洋 --- 依赖注入那些事儿
依赖注入产生的背景:
随着面向对象分析与设计的发展,一个良好的设计,核心原则之一就是将变化隔离,使得变化部分发生变化时,不变部分不受影响。为了做到这一点,要利用面向对象中的多态性,使用多态性后,客户类不再直接依赖服务类,而是依赖于一个抽象的接口,这样,客户类就不能在内部直接实例化具体的服务类。但是,客户类在运作中又客观需要具体的服务类提供服务,因为接口是不能实例化去提供服务的。就产生了“客户类不准实例化具体服务类”和“客户类需要具体服务类”这样一对矛盾。为了解决这个矛盾,开发人员提出了一种模式:客户类定义一个注入点,用于服务类的注入,而客户类的客户类负责根据情况,实例化服务类,注入到客户类中,从而解决了这个矛盾。
依赖注入的正式定义:
依赖注入(Dependency Injection),是这样一个过程:由于某客户类只依赖于服务类的一个接口,而不依赖于具体服务类,所以客户类只定义一个注入点。在程序运行过程中,客户类不直接实例化具体服务类实例,而是客户类的运行上下文环境或专门组件负责实例化服务类,然后将其注入到客户类中,保证客户类的正常运行。
说了这么多依赖注入的解释,那什么IOC容器,用于实现依赖注入功能的组件或框架,就是IoC Container,比如本框架中用到的 autofac。
从零开始写C# MVC框架之--- 服务接口与实现 ,文章只描述了接口和实现,重点是面向接口编程的方式,但是控制器调用接口,接口怎样去自动调用实现类,就是本章讨论的重点,只要实现autofac的注入功能,就能解决 控制器中调用接口,接口自动调用服务实现类 。
以上是理论讲解,下面结合系统代码:新增 Zy.Utility.ServicesProvider 项目,用于实现 autofac 依赖注入功能
实现原理,插件配置和反射获取程序集,再创建接口实例。
1、添加 Autofac 、Autofac.Configuration 的引用
2、获取程序集配置信息,用于反射获取接口与服务的程序集,再用 (T)Activator.CreateInstance 方法创建服务接口实现类实例
/// <summary> /// 实例创建代理 /// </summary> /// <typeparam name="T"></typeparam> public static class Instance<T> { /// <summary> /// 配置文件节处理者 /// </summary> static SectionHandler handler; /// <summary> /// 已手动配置的服务对应关系 /// </summary> static Hashtable ServiceNameSpaceMapper = null; /// <summary> /// 已注册的类型 /// </summary> static Dictionary<Type, Type> RegistedTypes = new Dictionary<Type, Type>(); /// <summary> /// 初始化 /// </summary> static Instance() { var reader = new ConfigurationSettingsReader("autofac"); handler = reader.SectionHandler; GetDefaultNamespaceRegisterMapper(); } /// <summary> /// 检查是否已经进行了显示的配置 /// </summary> /// <typeparam name="T">待检查的类型</typeparam> /// <returns>如果已经在配置文件中配置返回true,否则返回false</returns> static bool HasConfiguration<T>() { return handler.Components.Any(item => item.Service.Contains(typeof(T).FullName)); } /// <summary> /// 自动创建对应类型的实现 /// </summary> public static T Create { get { try { var hasconfiguration = HasConfiguration<T>(); var interfaceType = typeof(T); if (!hasconfiguration)//配置文件中未配置,采用默认注册 { if (!RegistedTypes.ContainsKey(interfaceType)) RegisteType<T>(); } var targetImplementType = RegistedTypes[interfaceType]; return (T)Activator.CreateInstance(targetImplementType); } catch (Exception ex) { throw new ServiceInstacnceCreateException(typeof(T).Name + "服务实例创建失败", ex); } } } /// <summary> /// 注册T类型 /// </summary> /// <typeparam name="T"></typeparam> static void RegisteType<T>() { var interfaceType = typeof(T); string fullName = interfaceType.FullName; string iserviceName = interfaceType.Name; lock (fullName) { if (!RegistedTypes.ContainsKey(interfaceType)) { string namespaceName = fullName.Substring(0, fullName.LastIndexOf('.'));//获取目标类型命名空间 string implementClass = ServiceNameSpaceMapper[namespaceName] as string;//从配置中获取对应命名空间的实现命名空间的名称 if (implementClass == null) throw new ApplicationException("未配置" + fullName + "的实现"); string nameSpace = implementClass.Split(',')[0];//获取对应实现类的命名空间 string assembly = implementClass.Split(',')[1];//获取对应实现类的程序集名称 string implementName = iserviceName.Substring(1);//获取对应实现类的名称 string className = string.Format("{0}.{1}, {2}", nameSpace, implementName, assembly);//获取对应实现类的全名 Type implementType = Type.GetType(className);//根据实现类全名创建类型 if (implementType == null) throw new ApplicationException("未找到" + className); RegistedTypes.Add(interfaceType, implementType);//将目标类型加入已注册类型列表中,表示已经注册过该类型的实现 } } } /// <summary> /// 获取手动配置的命名空间注册对应关系 /// </summary> static void GetDefaultNamespaceRegisterMapper() { ServiceNameSpaceMapper = new Hashtable(); var config = ConfigurationManager.GetSection("serviceProvider") as ServiceProviderConfig; foreach (var item in config.Items) { if (ServiceNameSpaceMapper.ContainsKey(item.Interface)) throw new ApplicationException("配置文件中最多只能配置一个" + item.Interface + "的实现"); ServiceNameSpaceMapper.Add(item.Interface, item.NameSpace + "," + item.Assembly); } } }
3、新建一个ServiceHelper类,用于调用 上面代码的 Create 方法,Web控制器使用此类。
4、在Web项目的web.config中配置,服务接口和实现的命名空间分别是:Zy.Xn.IServices 、 Zy.Xn.Services ,因此,配置代码如下:
<configSections> <section name="autofac" type="Autofac.Configuration.SectionHandler, Autofac.Configuration" /> <section name="serviceProvider" type="Zy.Utility.ServicesProvider.ServiceProviderConfig,Zy.Utility.ServicesProvider" /> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> </configSections>
<serviceProvider> <item interface="Zy.Xn.IServices" assembly="Zy.Xn.Services" namespace="Zy.Xn.Services"></item> </serviceProvider>以上是依赖注入的原理和实现,下面是在项目中的使用,演示用户登录功能
1、用户服务接口:
public interface IUserService : IService { /// <summary> /// 获取用户 /// </summary> /// <param name="loginUserName"></param> /// <returns></returns> User GetUser(string loginUserName); }
2、用户服务接口实现:
public class UserService : ServiceBase, IUserService { /// <summary> /// 获取用户 /// </summary> /// <param name="userName"></param> /// <returns></returns> public User GetUser(string loginUserName) { return context.Users.FirstOrDefault(item => item.LoginUserName == loginUserName); } }3、登录功能LoginController:
/// <summary>/// 登录/// </summary>/// <param name="userName">用户名</param>/// <param name="password">密码</param>/// <returns></returns>[HttpPost]public JsonResult Login(string userName, string password){ bool flag = false; string msg = string.Empty; if (!string.IsNullOrWhiteSpace(userName) && !string.IsNullOrWhiteSpace(password)) {var user = <strong>ServiceHelper.Create<IUserService>().GetUser(userName)</strong>;if (user != null){ if (user.LoginPassword == password) {Session[CacheKeys.User_Info_Cache_Key] = user;Session.Timeout = CacheKeys.User_Info_Cache_Time;msg = "登录成功";flag = true; } elsemsg = "密码错误";}else msg = "不存在该用户"; } elsemsg = "请传入用户名和密码"; return Json(new { success = flag , msg = msg});}
OK,大功告成,以后项目中所有的接口调用都是如此,只调接口即可
- 从零开始写C# MVC框架之--- 用autofac ioc 容器实现依赖注入
- Ioc容器-Autofac 之四-依赖注入框架Autofac的简单使用
- C#使用AutoFac实现IOC依赖注入
- MVC+ICO AutoFac 依赖注入框架
- 依赖注入容器Autofac
- AutoFac IoC DI 依赖注入
- 从零开始写C# MVC框架之--- 服务接口与实现
- autofac注入WCF IOC容器
- 从零开始写C# MVC框架之--- 开篇
- IOC(控制反转和依赖注入)之Autofac
- 从零实现MVC框架之依赖注入IOC(7)
- 《从零开始写Javaweb框架》知识点--依赖注入的实现
- asp.net mvc Autofac 依赖注入框架 使用
- Spring框架学习【IoC容器依赖注入】
- Asp.mvc(三) ~ 使用 Autofac 实现依赖注入
- IOC接口注入之Autofac
- MVC | 依赖注入 AutoFac (构造函数注入)
- IOC容器注入依赖
- 单片机==流水灯(1)
- hdu 5873 Football Games
- 【数据库】E-R图向关系模型转换的规则
- javascript淘宝主图放大镜功能
- Linq查询与方法调用
- 从零开始写C# MVC框架之--- 用autofac ioc 容器实现依赖注入
- Java设计模式——单例模式(Singleton Pattern)
- 视频编解码学习之三:变换,量化与熵编码
- PHP 5.5 新特性
- Codeforces482B【线段树构造】
- 线程和进程主要是运用在技术存储
- 面试题一:实现两个线程交替打印数字
- 什么是XML?
- LibGdx文档译读(八)LifecycleListener接口