• .NET架构小技巧(5)——反射,架构人员法宝III


      通过两篇博文,我们了解到,反射是通过非实例化(new)的手段来对对象和对象内的成员访问的,不仅仅如此,反射还可以突破访问修饰符的限制,以上帝视角来窥探对象内部全部成员(字段,属性,方法),包括private成员,这样一来,为我们从另外一个层次去设计程序架构,松散模块耦合,提供了强大而有力的支撑。

      本篇博文案例,分离的更彻底,完全上帝视角,说一下前情提要:对于His厂商来说,自己的His只有一份,但His要对接的医保有可能千变万化,His不可能要对接全部医保,所以这里要解耦,那首先要定义一个接口,来完成规范的定义,只要His和医保接口都符合这个规范就行,于是接口出现了:

    using System;
    
    namespace HisMedical
    {
        /// <summary>
        /// HIS
        /// </summary>
        public interface IHis
        {
            /// <summary>
            /// his登记号
            /// </summary>
            string RegisterID { set; }
            /// <summary>
            /// 住院登记
            /// </summary>
            /// <returns></returns>
            dynamic Register();
            /// <summary>
            /// 缴费
            /// </summary>
            /// <returns></returns>
            dynamic Fee();
        }
    }

      这个接口封装成一个单独的dll 叫HisMedical.dll

      His中首先要实现这个接口,完成His中所有动作的连动调用,这里做了两个动态,一个是登记住院,一个是住院缴费:

      /// <summary>
            /// his登记住院
            /// </summary>
            /// <param name="his"></param>
            /// <returns></returns>
            static string Register(IHis his)
            {
                var registerID = DateTime.Now.ToString("yyyyMMddHHmmss");
                Console.WriteLine($"*****完成His的登记,登记号:{registerID}");
                his.RegisterID = registerID;
                var result = his.Register();
                return registerID;
            }
            /// <summary>
            /// his缴费
            /// </summary>
            /// <param name="his"></param>
            /// <param name="registerID"></param>
            /// <returns></returns>
            static bool Fee(IHis his, string registerID)
            {
                Console.WriteLine($"*****完成His的结算,登记号:{registerID}");
                his.RegisterID = registerID;
                var result = his.Fee();
                return true;
            }

      接下来实现医保接口的dll就可以了:

      先看个东软的:

    using HisMedical;
    using System;
    
    namespace NeusoftMedical
    {
        /// <summary>
        /// 东软接口
        /// </summary>
        public class NeusoftMedical : IHis
        {
            /// <summary>
            /// his登记号
            /// </summary>
            public string RegisterID { set; private get; }
            /// <summary>
            /// 缴费
            /// </summary>
            /// <returns></returns>
            public dynamic Fee()
            {
                Console.WriteLine("-----完成对东软医保的住院缴费");
                return true;
            }
            /// <summary>
            /// 住院登记
            /// </summary>
            /// <returns></returns>
            public dynamic Register()
            {
                Console.WriteLine("-----完成对东软医保的住院登记");
                return true;
            }
        }
    }

      再看个银海的:

    using HisMedical;
    using System;
    
    namespace YiHaiMedical
    {
        /// <summary>
        /// 银海接口
        /// </summary>
        public class YinHaiMedical : IHis
        {
            /// <summary>
            /// his登记号
            /// </summary>
            public string RegisterID { set; private get; }
            /// <summary>
            /// 缴费
            /// </summary>
            /// <returns></returns>
            public dynamic Fee()
            {
                Console.WriteLine("=====完成对银海医保的住院缴费");
                return true;
            }
            /// <summary>
            /// 住院登记
            /// </summary>
            /// <returns></returns>
            public dynamic Register()
            {
                Console.WriteLine("=====完成对银海医保的住院登记");
                return true;
            }
        }
    }

      每个接口的实现,依赖RegisterID从His的读库中组织对应的数据就ok,最大限度的与His解耦。

      His中究竟是怎么调用不同的接口呢?我们可以把医保的dll的路径配置到一个表里,或配置文件里,当His启动时,自动加载这些dll就ok了,看代码怎么加载。

     static void Main(string[] args)
            {
                while (true)
                {
                    Console.WriteLine("1、东软  2、银海");
                    var no = Console.ReadLine();
                    Console.WriteLine("1、住院登记   2、住院结算");
                    var busNo = Console.ReadLine();
                    var path = "";
                    switch (no)
                    {
                        case "1":
                            path = @"C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\Architecture\NeusoftMedical\bin\Debug\netstandard2.0\NeusoftMedical.dll";
                            break;
                        case "2":
                            path = @"C:\MyFile\Source\Repos\Asp.NetCoreExperiment\Asp.NetCoreExperiment\Architecture\YiHaiMedical\bin\Debug\netstandard2.0\YiHaiMedical.dll";
                            break;
                    }
                    //从文件加载应用程序集并得到具体类型
                    var medicalType = Assembly.LoadFile(path).GetTypes().FirstOrDefault(t => t.GetInterfaces().Where(s => s.Name == "IHis").Count() > 0);
                    IHis his = (IHis)Activator.CreateInstance(medicalType);
                    var registerID = "";
                    switch (busNo)
                    {
                        case "1":
                            registerID = Register(his);
                            break;
                        case "2":
                            if (registerID != "")
                            {
                                Fee(his, registerID);
                            }
                            else
                            {
                                Console.WriteLine("请先登记住院");
                            }
                            break;
                    }
                }
            }

      代码中第一个switch是医保接口选择,看从配置文件中加载那个接口,第二个switch相当于His中执行的某个操作。不难看出通过反射加载dll,最大限度上解耦了His与医保接口,以后有什么新医保接口要对接,对His来说无感(本例中有可能不是无感的,因为这只是一个简单的代码,关于医保异步调用,还有特殊接口对应等,都没有实现)。

      通过三篇博文,我们简单看了一下反射的能力,可以让架构人员自由发挥,前两篇,通过集中开发两个转换方法,其他开发都成了体力活(初级程序员就能实现),本篇更让架构师不管具体医保接口的实现,轻松应实现对接,所以说:反射,架构人员法宝

    想要更快更方便的了解相关知识,可以关注微信公众号 
     

  • 相关阅读:
    kettle 连接 SQL Server 异常
    Quartz.NET
    过滤器和拦截器
    Spring Web MVC(一)
    Spring(三)之自动装配、表达式
    spring(四)之基于注解(Annotation-based)的配置.md
    Spring(一)之IOC、bean、注入
    Spring(二)之配置.md
    cookie和session详解
    jsp基础与提高(EL、JSTL)
  • 原文地址:https://www.cnblogs.com/axzxs2001/p/15854543.html
Copyright © 2020-2023  润新知