网站的建设思路,小型建筑公司名字大全,买链接做网站 利润高吗,网站图片加载顺序如题#xff0c;这是我的心声#xff0c;反射在我的开发中用的频次还是比较高的#xff0c;有一本万利的感觉#xff0c;一段复杂的代码#xff0c;可以节省大量的时间#xff1b;但带来的一个问题性能相对较差#xff0c;所以要选择适合的场景使用。关于C#中的反射基本… 如题这是我的心声反射在我的开发中用的频次还是比较高的有一本万利的感觉一段复杂的代码可以节省大量的时间但带来的一个问题性能相对较差所以要选择适合的场景使用。关于C#中的反射基本用法这里不作详细介绍官网有详细的说明。下面是在网上找了一个医保接口的案件比如有两个业务接口033027这个接口的传输内容类似xml但又是有区别的不是严格意义上的xml格式。医院就诊卡接口规范业务033输入参数RequestTradeCode业务编号/TradeCodeBeginDate开始日期/BeginDateEndDate结束日期/EndDate
/Request
输出参数ResponsePatientId病历编号/PatientIdSiHisOrderNoHIS端结算流水/SiHisOrderNoPubCost医保统筹支付元/PubCostPayCost医保帐户支付元/PayCostOwnCost患者个人自付元/OwnCostTotCost本次结算总额元/TotCostTransType结算类别1消费0退费/TransTypeOperCode操作人员编号/OperCodeOperName操作人员姓名/OperNamePayType支付方式/PayTypeInvoicesINum单据编号/INumIType单据类别/InvoiceTypeISum单据金额元/ISum/Invoices
/Request
医院就诊卡接口规范业务027输入参数RequestTradeCode交易码(见上表交易代码)/TradeCodeDate交易日期YYYYMMDD/DateTime交易时间HHMMSS/TimeInvoiceNo发票号/InvoiceNoTransType交易类别/TransType
/Request
输出参数ResponseTradeCode业务编号/TradeCodeResult返回值0 成功其他失败/ResultErr错误描述信息/ErrHospitalTransNO本次交易流水/HospitalTransNOFeesFeefybm收费项目编码/fybmfymc收费项目名称/fymcksbm开立科室编码/ksbmksmc开立科室名称/ksmcysbm开立医生编码/ysbmysxm开立医生姓名/ysxmkdsj开单时间(yyyy-MM-dd HH:mm:ss)/kdsjsfsj收费时间(yyyy-MM-dd HH:mm:ss)/sfsjfysl数量/fyslyxbz有效标志/yxbzczy收费人员编号/czyzxks执行科室编号/zxksInvoiceNo单据编号/InvoiceNo/Fee....../Fees
/Response
这个医保接口的对接方式入参都是一个Request节点出参都是Response节点至少是调用dll还是通过什么协议发送参数接收参数是另外一会事所以咱们重点来说架构小技巧。首先思考的是我们在.net中是面向对应编程这些接口的输入参数输出参数应该对应成实体当然用字符串拼接也可以但当接口众多时一点一点拼接势必会出错率高同时个性化处理非常麻烦另一方面显得比较low。这时反射大显身手的机会就来了假如我只要按输入参数输出参数的属性定义好实体类再造一个神器能把实体转成输入参数字符串也能把输出参数转成实体类对我们来说就是完全的OOP了“辛苦两个转换方法幸福所有接口”当然对开发一个完整的医保接口来说另一个难点是从现有系统中组织输入参数实体类和回写输出参数实体但也不是架构技巧的重点。还是上代码吧using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;namespace ArchitectureDemo03
{class Program{static void Main(string[] args){var readCard033 new ReadCard033{TradeCode 033,BeginDate DateTime.Now,EndDate 20200102};var readcard033Back SendReadCard033Back(readCard033);Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(readcard033Back));var readCard027 new ReadCard027{Date 20201212,InvoiceNo abcd,Time 121212,TradeCode 003,TransType 123};var readCard027Back SendReadCard027Back(readCard027);Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(readCard027Back));}/// summary/// 模拟输入函数与输出xml对应集合以作mock/// /summarystatic Dictionarystring, string BackDic new Dictionarystring, string {{ReadCard033 ,ResponsePatientId病历编号/PatientIdSiHisOrderNoHIS端结算流水/SiHisOrderNoPubCost1/PubCostPayCost2/PayCostOwnCost3/OwnCostTotCost4/TotCostTransType1/TransTypeOperCode操作人员编号/OperCodeOperName操作人员姓名/OperNamePayType支付方式/PayTypeInvoicesINum单据编号/INumInvoiceType单据类别/InvoiceTypeISum5/ISum/Invoices
/Response},{ ReadCard027,$ResponseTradeCode业务编号/TradeCodeResult0/ResultErr错误描述信息/ErrHospitalTransNO本次交易流水/HospitalTransNOFeesFeefybm收费项目编码/fybmfymc收费项目名称/fymcksbm开立科室编码/ksbmksmc开立科室名称/ksmcysbm开立医生编码/ysbmysxm开立医生姓名/ysxmkdsj2020-12-12 13:14:15/kdsjsfsj2020-12-12 13:14:15/sfsjfysl10/fyslyxbz有效标志/yxbzczy收费人员编号/czyzxks执行科室编号/zxksInvoiceNo单据编号/InvoiceNo/Fee Feefybm收费项目编码/fybmfymc收费项目名称/fymcksbm开立科室编码/ksbmksmc开立科室名称/ksmcysbm开立医生编码/ysbmysxm开立医生姓名/ysxmkdsj2020-12-12 13:14:15/kdsjsfsj2020-12-12 13:14:15/sfsjfysl10/fyslyxbz有效标志/yxbzczy收费人员编号/czyzxks执行科室编号/zxksInvoiceNo单据编号/InvoiceNo/Fee /Fees
/Response}};/// summary/// 封装调用接口/// /summary/// typeparam nameT输出参数类型/typeparam/// param namerequest输入参数/param/// returns/returnsstatic T SendT(Request request) where T : class{Console.WriteLine(输入参数);Console.WriteLine(request.ToXML());var backXML BackDic[request.GetType().Name];return request.ToResponse(typeof(T), backXML) as T;}}/// summary/// 请求父类/// /summaryabstract class Request{public override string ToString(){var requestSB new StringBuilder();var type this.GetType();//遍历属性获取属性值foreach (var pro in type.GetProperties()){//处理Request的子类所有输入参数都应该继承Requestif (pro.PropertyType.IsSubclassOf(typeof(Request))){requestSB.AppendLine(${pro.Name});requestSB.AppendLine(${pro.GetValue(this)});requestSB.AppendLine($/{pro.Name});}else{//处理DateTime类型属性if (pro.PropertyType.IsAssignableFrom(typeof(DateTime))){var value Convert.ToDateTime(pro.GetValue(this)).ToString(yyyyMMddHHMMSS);requestSB.AppendLine(${pro.Name}{value}/{pro.Name});}else{requestSB.AppendLine(${pro.Name}{pro.GetValue(this)}/{pro.Name});}}}return requestSB.ToString().Trim();}/// summary/// 输成xml输入参数/// /summary/// returns/returnspublic string ToXML(){return $Request\n{this}\n/Request;}/// summary/// 输出参数xml转成实体类/// /summary/// param nametype输出参数类型/param/// param namexml输出参数xml/param/// returns/returnspublic object ToResponse(Type type, string xml){xml $?xml version1.0 encodingutf-8?{xml};var xmlDoc new XmlDocument();xmlDoc.LoadXml(xml);var instance Activator.CreateInstance(type);foreach (var pro in type.GetProperties()){//自定义实体类属性利用在同一个命名空间里来解瘊这个事情if (pro.PropertyType.Namespace this.GetType().Namespace){var xmlElement xmlDoc.GetElementsByTagName(pro.Name);if (xmlElement.Count 0){var response ToResponse(pro.PropertyType, ${pro.Name}{xmlElement[0].InnerXml}/{pro.Name});pro.SetValue(instance, response);}}else{//泛型集合实体类属性if (pro.PropertyType.IsGenericType){//获取泛型集合属性的类型var subType pro.PropertyType.GetGenericArguments()[0];var xmlElement xmlDoc.GetElementsByTagName(pro.Name);if (xmlElement.Count 0){//生成泛型集合属性的实体类var list Activator.CreateInstance(pro.PropertyType) as IList;//把输出字符串中的列表对应数据添加到泛型属性集合中foreach (XmlNode childItem in xmlElement[0].ChildNodes){if (childItem.ChildNodes.Count 0){var subInstance ToResponse(subType, ${subType.Name}{xmlElement[0].ChildNodes[0].InnerXml}/{subType.Name});list.Add(subInstance);}}//设置泛型集合属性的值pro.SetValue(instance, list);}}else{//普通属性var xmlElement xmlDoc.GetElementsByTagName(pro.Name);if (xmlElement.Count 0){var value Convert.ChangeType(xmlElement[0].InnerText, pro.PropertyType);pro.SetValue(instance, value);}}}}return instance;}}/// summary/// 医院就诊卡接口规范业务033/// /summaryclass ReadCard033 : Request{/// summary/// 业务编号/// /summarypublic string TradeCode { get; set; }/// summary/// 开始日期/// /summarypublic DateTime BeginDate { get; set; }/// summary/// 结束日期/// /summarypublic string EndDate { get; set; }}/// summary/// 医院就诊卡接口规范业务033输出参数/// /summaryclass ReadCard033Back{/// summary/// 病历编号/// /summarypublic string PatientId { get; set; }/// summary/// HIS端结算流水/// /summarypublic string SiHisOrderNo { get; set; }/// summary/// 医保统筹支付元/// /summarypublic decimal PubCost { get; set; }/// summary/// 医保帐户支付元/// /summarypublic decimal PayCost { get; set; }/// summary/// 患者个人自付元/// /summarypublic decimal OwnCost { get; set; }/// summary/// 本次结算总额元/// /summarypublic decimal TotCost { get; set; }/// summary/// 结算类别1消费0退费/// /summarypublic int TransType { get; set; }/// summary/// 操作人员编号/// /summarypublic string OperCode { get; set; }/// summary/// 操作人员姓名/// /summarypublic string OperName { get; set; }/// summary/// 支付方式/// /summarypublic string PayType { get; set; }/// summary/// 单据信息/// /summarypublic Invoices Invoices { get; set; }}/// summary/// 单据/// /summaryclass Invoices{/// summary/// 单据编号/// /summarypublic string INum { get; set; }/// summary/// 单据类别/// /summarypublic string InvoiceType { get; set; }/// summary/// 单据金额元/// /summarypublic decimal ISum { get; set; }}/// summary/// 医院就诊卡接口规范业务027/// /summaryclass ReadCard027 : Request{/// summary/// 交易码(见上表交易代码)/// /summarypublic string TradeCode { get; set; }/// summary/// 交易日期YYYYMMDD/// /summarypublic string Date { get; set; }/// summary/// 交易时间HHMMSS/// /summarypublic string Time { get; set; }/// summary/// 发票号/// /summarypublic string InvoiceNo { get; set; }/// summary/// 交易类别/// /summarypublic string TransType { get; set; }}/// summary/// 医院就诊卡接口规范业务027输出参数/// /summaryclass ReadCard027Back{/// summary/// 业务编号/// /summarypublic string TradeCode { get; set; }/// summary/// 返回值0 成功其他失败/// /summarypublic string Result { get; set; }/// summary/// 错误描述信息/// /summarypublic string Err { get; set; }/// summary/// 本次交易流水/// /summarypublic string HospitalTransNO { get; set; }/// summary/// 明细列表/// /summarypublic ListFee Fees { get; set; }}/// summary/// 明细/// /summaryclass Fee{/// summary/// 收费项目编码/// /summarypublic string fybm { get; set; }/// summary/// 收费项目名称/// /summarypublic string fymc { get; set; }/// summary/// 开立科室编码/// /summarypublic string ksbm { get; set; }/// summary/// 开立科室名称/// /summarypublic string ksmc { get; set; }/// summary/// 开立医生编码/// /summarypublic string ysbm { get; set; }/// summary/// 开立医生姓名/// /summarypublic string ysxm { get; set; }/// summary/// 开单时间(yyyy-MM-dd HH:mm:ss)/// /summarypublic string kdsj { get; set; }/// summary/// 收费时间(yyyy-MM-dd HH:mm:ss)/// /summarypublic string sfsj { get; set; }/// summary/// 数量/// /summarypublic string fysl { get; set; }/// summary/// 有效标志/// /summarypublic string yxbz { get; set; }/// summary/// 收费人员编号/// /summarypublic string czy { get; set; }/// summary/// 执行科室编号/// /summarypublic string zxks { get; set; }/// summary/// 单据编号/// /summarypublic string InvoiceNo { get; set; }}
}
在上面代码中重点是Request这个抽象类其实原ToXML中把实体类转成输入参数字符串ToResponse是把输出字符串转成实体供程序使用。这两个方法的具体实现在代码中有注释这是使用反射属性来实现转换的当然这种转换用XmlSerializer也可以实现但这样就失去了对属性的灵活控制比如demo中的时间类型属性的转换。“辛苦两个转换方法幸福所有接口”就是ToXML和ToResponse如果这个医保还有几十个接口那就只用定义每个业务函数对应的输入参数输出参数实体类就可以了。这样简化了程序模块的耦合层次也很清晰但你可能在问性能了确实反射带来灵活的同时就会损失性能但大部分医保接口都是以dll的形式存在和his系统配合使用就是一个时刻只有一个接口在调用对性能的容忍度还是够用的。