Fork me on GitHub
自定义的配置文件实现动态注入

自定义的配置文件实现动态注入

一、前言

大家使用了很多依赖注入的组件,不懂得话可以搜索一下博客园相关的博文。这篇博文主要是介绍如何使用配置,通过自定义的的元素节点动态实现依赖注入。这里涉及了几个相关的类: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小柯

posted on 2015-11-17 11:43  HackerVirus  阅读(1501)  评论(0编辑  收藏  举报