自定义的配置文件实现动态注入
一、前言
大家使用了很多依赖注入的组件,不懂得话可以搜索一下博客园相关的博文。这篇博文主要是介绍如何使用配置,通过自定义的的元素节点动态实现依赖注入。这里涉及了几个相关的类:ConfigurationSection,ConfigurationElementCollection和ConfigurationElement。
二、测试代码划分
简单给给大家看一下测试Demo
三、实现过程
1.配置文件
<?xml version="1.0" encoding="utf-8" ?> <configuration> <!--第一步--> <!--configSections要定义最上面,定义configSections,name是对应下面元素名,type(类的位置,程序集)--> <configSections> <section name="serviceMappingsConfiguration" type="UserDefinedConfiguration.Configuration.ServiceSetting, UserDefinedConfiguration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/> </configSections> <!--第二步,配置接口名和对应的接口实例位置--> <serviceMappingsConfiguration> <serviceMappings> <serviceMapping interfaceName="IOrderService" instanceName="UserDefinedConfiguration.Service.OrderService, UserDefinedConfiguration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> <serviceMapping interfaceName="IProductService" instanceName="UserDefinedConfiguration.Service.ProductService, UserDefinedConfiguration, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> </serviceMappings> </serviceMappingsConfiguration> <startup> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> </startup> </configuration>
2.创建一个类ServiceSetting,继承ConfigurationSection,定义一个节点集合属性ServiceMappingCollection
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace UserDefinedConfiguration.Configuration { public class ServiceSetting : ConfigurationSection { [ConfigurationProperty("serviceMappings", IsDefaultCollection = true)] //声明,实例化配置属性 public ServiceMappingCollection ServiceMappings { get { return (ServiceMappingCollection)base["serviceMappings"]; } } } }
3.创建的ServiceMappingCollection类继承ConfigurationElementCollection,重写ConfigurationElementCollection的方法
在ServiceMappingCollection中也用到了自己定义的ServiceMappingElement类。
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace UserDefinedConfiguration.Configuration { public sealed class ServiceMappingCollection : ConfigurationElementCollection { //实例化一个新的元素(子节点) protected override ConfigurationElement CreateNewElement() { return new ServiceMappingElement(); } //获取节点的Key名字 protected override object GetElementKey(ConfigurationElement element) { return ((ServiceMappingElement)element).InterfaceName; } //配置节点集合类型 public override ConfigurationElementCollectionType CollectionType { get { return ConfigurationElementCollectionType.BasicMap; } } //子节点名 protected override string ElementName { get { return "serviceMapping"; } } public new ServiceMappingElement this[string interfaceName] { get { return (ServiceMappingElement)BaseGet(interfaceName); } } } }
4.创建的ServiceMappingElement类继承ConfigurationElement,在ServiceMappingElement设置好和 配置文件定义节点serviceMapping的属性关系
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; namespace UserDefinedConfiguration.Configuration { //设置元素对应关系 public sealed class ServiceMappingElement : ConfigurationElement { [ConfigurationProperty("interfaceName",IsKey = true, IsRequired = true)] //这里指定了Key ,IsKey = true public string InterfaceName { get { return (string)this["interfaceName"]; } set { this["interfaceName"] = value; } } [ConfigurationProperty("instanceName", IsRequired = true)] //这里没指定Key public string InstanceName { get { return (string)this["instanceName"]; } set { this["instanceName"] = value; } } } }
5.自定义的IProductService服务类已经它的实现
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace UserDefinedConfiguration.IService { public interface IProductService { void GetProductByID(string id); } }
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using UserDefinedConfiguration.IService; namespace UserDefinedConfiguration.Service { public class ProductService:IProductService { public void GetProductByID(string id) { Console.WriteLine("得到商品ID:"+id); } } }
6.测试
通过(ServiceSetting)ConfigurationManager.GetSection("serviceMappingsConfiguration") 注册上面配置好的所有信息,并通过反射创建接口的实例,存入到缓存中,减少系统的压力
using System; using System.Collections.Generic; using System.Configuration; using System.Linq; using System.Text; using System.Threading.Tasks; using UserDefinedConfiguration.Configuration; using UserDefinedConfiguration.IService; namespace Test { class Program { static void Main(string[] args) { IProductService productService = Program.GetService<IProductService>(); productService.GetProductByID("9527"); IOrderService orderService = Program.GetService<IOrderService>(); orderService.Create("1000"); Console.ReadKey(); } private static Dictionary<string, object> dic = new Dictionary<string, object>(); public static TIService GetService<TIService>() where TIService : class { TIService service = default(TIService); string interfaceName = typeof(TIService).Name; if (!dic.ContainsKey(interfaceName)) { //最重要的方法,初始化配置阶段所有信息 ServiceSetting settings = (ServiceSetting)ConfigurationManager.GetSection("serviceMappingsConfiguration"); //获取实例类型 Type instanceType = Type.GetType(settings.ServiceMappings[interfaceName].InstanceName); //创建类型实例 service = Activator.CreateInstance(instanceType) as TIService; dic.Add(interfaceName, service); } service = (TIService)dic[interfaceName]; return service; } } }
运行结果:
作者:Kero小柯