//获取接口数据let str: string = "['D1','D23','D17']";//将原来的'替换为",不然反序列化会失败str = str.replace(/'/g, "\"");//对字符串进行反序列化const ss = JSON.parse(str);//输出字符串console.log("===============")console.log("序列化之后的结果", ss)console.log("===============")let newArr = [];for (let i in ss) { //创建临时对象用户写入数据 let temp = { value: "", num: 0, str: "", }; //保存原字符串 temp.value = ss[i]; //获取数字 let numReg = /[0-9]+/g; temp.num = Number(numReg.exec(ss[i])[0]); //获取字符串 let strReg = /[A-Z]+/g; temp.str = strReg.exec(ss[i])[0]; //将临时对象添加到数组中 newArr.push(temp);}//正序console.log("=====正序======")newArr.sort(function (o1, o2) { return o1.num - o2.num;})console.log(newArr);//反序console.log("=====反序======")newArr.sort(function (o1, o2) { return o2.num - o1.num;})console.log(newArr);
]]>
当我们使用程序的时候,经常会出校误操作的选项,这个时候我们又希望回滚这个操作,也就是 “撤销” ,可以通过事务的方式每次记录之前的操作,也可以使用我们现在介绍的,快照模式。
在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,以便以后当需要时能将该对象恢复到原先保存的状态。
优点
缺点
/// <summary> /// 调用人 /// </summary> public class Chess { public Chess() { } public Chess(int color, int index_X, int index_Y, string chessName) { this.Color = color; this.Index_X = index_X; this.Index_Y = index_Y; this.ChessName = chessName; } public int Color { get; set; } public int Index_X { get; set; } public int Index_Y { get; set; } public string ChessName { get; set; } /// <summary> /// 创建备忘录 /// </summary> /// <param name="chess"></param> /// <returns></returns> public ChessMemory CreateMemory(Chess chess) { //对象克隆的时候要小心哦,如果直接复制,对象改变了也会导致备忘录的内容改变了, //所以这里使用了序列化与反序列化做一个深克隆 var serializeData = JsonSerializer.Serialize(chess); return JsonSerializer.Deserialize<ChessMemory>(serializeData); } /// <summary> /// 咋?还不给悔棋了? /// </summary> /// <param name="chessMemory"></param> public void Restore(ChessMemory chessMemory) { this.ChessName = chessMemory.ChessName; this.Index_X = chessMemory.Index_X; this.Index_Y = chessMemory.Index_Y; this.Color = chessMemory.Color; } public override string ToString() { string colorName = this.Color == 1 ? "红方" : "黑方"; return $"{colorName}{this.ChessName}:落子({this.Index_X},{this.Index_Y})"; } }
/// <summary> /// 备忘录信息 /// </summary> public class ChessMemory { public int Color { get; set; } public int Index_X { get; set; } public int Index_Y { get; set; } public string ChessName { get; set; } public int Step { get; set; } }
public class ChessCaretaker { private int Step = 0; private List<ChessMemory> chessMemorieLinked = new List<ChessMemory>(); private List<ChessMemory> chessMemorieLinkedBackup = new List<ChessMemory>(); public void AddMemory(ChessMemory chessMemory) { chessMemorieLinked.Add(chessMemory); } public ChessMemory PreviousStep() { var lastData = chessMemorieLinked.LastOrDefault(); chessMemorieLinkedBackup.Add(lastData); chessMemorieLinked.Remove(lastData); return chessMemorieLinked.LastOrDefault(); } public ChessMemory NextStep() { var lastData = chessMemorieLinkedBackup.LastOrDefault(); chessMemorieLinked.Add(lastData); chessMemorieLinkedBackup.Remove(lastData); return lastData; } }
protected readonly ITestOutputHelper Output; public UnitTest1(ITestOutputHelper tempOutput) { Output = tempOutput; } [Fact] public void Test1() { //使用Fixture构造一个数据填充 var gamerDataFixTure = new Fixture(); //准备“备忘录” var chessCaretaker = new ChessCaretaker(); Output.WriteLine("开始下棋"); var gamerData = new Chess(); for (int i = 0; i < 10; i++) { //下一步棋 gamerData = gamerDataFixTure.Create<Chess>(); Output.WriteLine($"保存记录:第{i}步"); Output.WriteLine(gamerData.ToString()); //添加到备忘录 chessCaretaker.AddMemory(gamerData.CreateMemory(gamerData)); } Output.WriteLine($"我要开始悔棋了"); //悔棋 for (int i = 0; i < 3; i++) { //获取上一步的数据 var previousData = chessCaretaker.PreviousStep(); if (previousData != null) { //还原上一步的数据 gamerData.Restore(previousData); Output.WriteLine($"上一步"); Output.WriteLine(gamerData.ToString()); } else { Output.WriteLine($"老板,已经帮你还原成初始值了!"); } } Output.WriteLine($"我要开始还原了"); //还原 for (int i = 0; i < 3; i++) { //获取下一步的数据 var nextStep = chessCaretaker.NextStep(); if (nextStep != null) { //还原下一步的数据 gamerData.Restore(nextStep); Output.WriteLine($"下一步"); Output.WriteLine(gamerData.ToString()); } else { Output.WriteLine($"不能下一步了,达咩哦!"); } } }
标准输出消息: 开始下棋 保存记录:第0步 黑方ChessName762d996e-cf26-4baf-a862-aeacbd709237:落子(193,163) 保存记录:第1步 黑方ChessNamebdace414-50f7-4a47-8c79-9b9a6947f437:落子(207,186) 保存记录:第2步 黑方ChessNameffc67c3a-45a5-4f83-9f6b-174e41652971:落子(137,146) 保存记录:第3步 黑方ChessName4914f594-9be7-4597-be7a-a99d4919bb81:落子(59,133) 保存记录:第4步 红方ChessName4e62f74d-55be-4d91-8efd-4b7cda01f9ad:落子(249,136) 保存记录:第5步 黑方ChessName95e1bcfe-1d39-4675-99a2-feda737982ea:落子(130,242) 保存记录:第6步 黑方ChessName3e59ce2e-ff03-470e-9ece-88adc76b6005:落子(23,69) 保存记录:第7步 黑方ChessName41f56898-173c-4397-a182-f11616541d14:落子(83,159) 保存记录:第8步 黑方ChessName3e99fa1f-29ac-4db5-999b-4051adaae6cf:落子(135,120) 保存记录:第9步 黑方ChessNamedc615762-1cdb-40d5-b2dd-7cdf1393421c:落子(17,87) 我要开始悔棋了 上一步 黑方ChessName3e99fa1f-29ac-4db5-999b-4051adaae6cf:落子(135,120) 上一步 黑方ChessName41f56898-173c-4397-a182-f11616541d14:落子(83,159) 上一步 黑方ChessName3e59ce2e-ff03-470e-9ece-88adc76b6005:落子(23,69) 我要开始还原了 下一步 黑方ChessName41f56898-173c-4397-a182-f11616541d14:落子(83,159) 下一步 黑方ChessName3e99fa1f-29ac-4db5-999b-4051adaae6cf:落子(135,120) 下一步 黑方ChessNamedc615762-1cdb-40d5-b2dd-7cdf1393421c:落子(17,87)测试运行成功。测试总数: 1 通过数: 1总时间: 1.0358 秒
]]>
上周开始了某个项目的接口对接,由于对方是WebApi,所以就用SoapUI进行调试啦。
刚开始用SoapUI调试还是很顺利的,当事情太过于顺利的时候往往就。。。。。
当前项目用的是代理的方式构建请求体,也就是烂大街的那种代码(贴最后了)
看着没啥毛病是吧,然鹅,我们正常看的WebService都是长酱紫的:
http://xxx.xxx.xxx.xxx:8090/PathologyAppInfo/PathologyAppInfoService.asmx
对方给的是酱紫的:
http://xxx.xxx.xxx.xx:11010/csp/healthshare/bkip/BKIP.AppInfo.PathologyAppInfo.BS.PathologyAppInfo.cls?CfgItem=PathologyAppInfoBS
是不是发现有点点不一样了!!!
是的,他们的尾巴带了
?CfgItem=PathologyAppInfoBS
然后,框架认不出来了。怎么办嘞,又要按时交付,于是乎内网穿透大法搞起来,添加添加WebService引用总可以吧。终究是我错付了,还是不行,还是异常400。
既然这条路走不通,曲线救国,SoapService归根到底就是一个Post/Get请求,一顿操作,分析了下SoapUI的请求过程,请求体抄起来:
于是乎,我又得到了一个新的错误,直接就跳转了,压根就调用不到啊。。。。。。。。。。。
百度就不用百度了,全网的ContentType都是Application/xml
经过一番努力,把ContentType改成Application/Soap+xml就行了!!!感天动地
public class WebServiceProxy { private readonly ILog _log = LogHelper.GetLog(); #region 私有变量和属性定义 /// <summary> /// web服务地址 /// </summary> private string _wsdlUrl = string.Empty; /// <summary> /// web服务名称 /// </summary> private string _wsdlName = string.Empty; /// <summary> /// 代理类命名空间 /// </summary> private string _wsdlNamespace = "FrameWork.WebService.DynamicWebServiceCalling.{0}"; /// <summary> /// 代理类类型名称 /// </summary> private Type _typeName = null; /// <summary> /// 程序集名称 /// </summary> private string _assName = string.Empty; /// <summary> /// 代理类所在程序集路径 /// </summary> private string _assPath = string.Empty; /// <summary> /// 代理类的实例 /// </summary> private object _instance = null; /// <summary> /// 代理类的实例 /// </summary> private object Instance { get { if (_instance == null) { _instance = Activator.CreateInstance(_typeName); return _instance; } else return _instance; } } #endregion #region 构造函数 public WebServiceProxy(string wsdlUrl) { if (string.IsNullOrWhiteSpace(wsdlUrl)) { return; } if (!wsdlUrl.Contains("wsdl")) { wsdlUrl += "?wsdl"; } this._wsdlUrl = wsdlUrl; string wsdlName = getWsclassName(wsdlUrl); this._wsdlName = wsdlName; this._assName = string.Format(_wsdlNamespace, wsdlName); this._assPath = Path.GetTempPath() + this._assName + getMd5Sum(this._wsdlUrl) + ".dll"; this.CreateServiceAssembly(); } #endregion #region 得到WSDL信息,生成本地代理类并编译为DLL,构造函数调用,类生成时加载 /// <summary> /// 得到WSDL信息,生成本地代理类并编译为DLL /// </summary> private void CreateServiceAssembly() { if (this.checkCache()) { this.initTypeName(); return; } if (string.IsNullOrEmpty(this._wsdlUrl)) { return; } try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_wsdlUrl); request.Timeout = 10000; request.ReadWriteTimeout = 10000; var response = request.GetResponse(); //使用WebClient下载WSDL信息 WebClient web = new WebClient(); Stream stream = web.OpenRead(this._wsdlUrl); ServiceDescription description = ServiceDescription.Read(stream);//创建和格式化WSDL文档 ServiceDescriptionImporter importer = new ServiceDescriptionImporter();//创建客户端代理代理类 importer.ProtocolName = "Soap"; importer.Style = ServiceDescriptionImportStyle.Client; //生成客户端代理 importer.CodeGenerationOptions = CodeGenerationOptions.GenerateProperties | CodeGenerationOptions.GenerateNewAsync; importer.AddServiceDescription(description, null, null);//添加WSDL文档 //使用CodeDom编译客户端代理类 CodeNamespace nmspace = new CodeNamespace(_assName); //为代理类添加命名空间 CodeCompileUnit unit = new CodeCompileUnit(); unit.Namespaces.Add(nmspace); this.checkForImports(this._wsdlUrl, importer); ServiceDescriptionImportWarnings warning = importer.Import(nmspace, unit); CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters parameter = new CompilerParameters(); parameter.ReferencedAssemblies.Add("System.dll"); parameter.ReferencedAssemblies.Add("System.XML.dll"); parameter.ReferencedAssemblies.Add("System.Web.Services.dll"); parameter.ReferencedAssemblies.Add("System.Data.dll"); parameter.GenerateExecutable = false; parameter.GenerateInMemory = false; parameter.IncludeDebugInformation = false; CompilerResults result = provider.CompileAssemblyFromDom(parameter, unit); provider.Dispose(); if (result.Errors.HasErrors) { string errors = string.Format(@"编译错误:{0}错误!", result.Errors.Count); foreach (CompilerError error in result.Errors) { errors += error.ErrorText; } throw new Exception(errors); } this.copyTempAssembly(result.PathToAssembly); this.initTypeName(); _log.Info($"ws代理:{_wsdlUrl}创建成功。"); } catch (Exception e) { _log.Fatal($"创建{_wsdlUrl}的webservice代理出现异常,异常信息为{e}。"); } } #endregion #region 执行Web服务方法 /// <summary> /// 执行代理类指定方法,有返回值 /// </summary> /// <param name="methodName">方法名称</param> /// <param name="param">参数</param> /// <returns>object</returns> public object ExecuteQuery(string methodName, object[] param) { object rtnObj; try { if (this._typeName == null) { throw new TypeLoadException("Web服务访问类名【" + this._wsdlName + "】不正确,请检查!"); } //调用方法 MethodInfo mi = this._typeName.GetMethod(methodName); if (mi == null) { throw new TypeLoadException("Web服务访问方法名【" + methodName + "】不正确,请检查!"); } try { _log.Debug($"调用接口{_wsdlName}----{methodName}参数:{param}"); rtnObj = mi.Invoke(Instance, param); } catch (TypeLoadException tle) { throw new TypeLoadException("Web服务访问方法【" + methodName + "】参数个数不正确,请检查!", new TypeLoadException(tle.StackTrace)); } } catch (Exception ex) { throw new Exception(ex.Message, new Exception(ex.StackTrace)); } return rtnObj; } /// <summary> /// 执行代理类指定方法,无返回值 /// </summary> /// <param name="methodName">方法名称</param> /// <param name="param">参数</param> public void ExecuteNoQuery(string methodName, object[] param) { try { if (this._typeName == null) { throw new TypeLoadException("Web服务访问类名【" + this._wsdlName + "】不正确,请检查!"); } //调用方法 MethodInfo mi = this._typeName.GetMethod(methodName); if (mi == null) { throw new TypeLoadException("Web服务访问方法名【" + methodName + "】不正确,请检查!"); } try { _log.Debug($"调用接口{_wsdlName}----{methodName}参数:{param}"); mi.Invoke(Instance, param); } catch (TypeLoadException tle) { throw new TypeLoadException("Web服务访问方法【" + methodName + "】参数个数不正确,请检查!", new TypeLoadException(tle.StackTrace)); } } catch (Exception ex) { throw new Exception(ex.Message, new Exception(ex.StackTrace)); } } #endregion #region 私有方法 /// <summary> /// 得到代理类类型名称 /// </summary> private void initTypeName() { Assembly serviceAsm = Assembly.LoadFrom(this._assPath); Type[] types = serviceAsm.GetTypes(); string objTypeName = ""; foreach (Type t in types) { if (t.BaseType == typeof(SoapHttpClientProtocol)) { objTypeName = t.Name; break; } } _typeName = serviceAsm.GetType(this._assName + "." + objTypeName); } /// <summary> /// 根据web service文档架构向代理类添加ServiceDescription和XmlSchema /// </summary> /// <param name="baseWSDLUrl">web服务地址</param> /// <param name="importer">代理类</param> private void checkForImports(string baseWsdlUrl, ServiceDescriptionImporter importer) { DiscoveryClientProtocol dcp = new DiscoveryClientProtocol(); dcp.DiscoverAny(baseWsdlUrl); dcp.ResolveAll(); foreach (object osd in dcp.Documents.Values) { if (osd is ServiceDescription) importer.AddServiceDescription((ServiceDescription)osd, null, null); ; if (osd is XmlSchema) importer.Schemas.Add((XmlSchema)osd); } } /// <summary> /// 复制程序集到指定路径 /// </summary> /// <param name="pathToAssembly">程序集路径</param> private void copyTempAssembly(string pathToAssembly) { File.Copy(pathToAssembly, this._assPath); } private string getMd5Sum(string str) { Encoder enc = System.Text.Encoding.Unicode.GetEncoder(); byte[] unicodeText = new byte[str.Length * 2]; enc.GetBytes(str.ToCharArray(), 0, str.Length, unicodeText, 0, true); MD5 md5 = new MD5CryptoServiceProvider(); byte[] result = md5.ComputeHash(unicodeText); StringBuilder sb = new StringBuilder(); for (int i = 0; i < result.Length; i++) { sb.Append(result[i].ToString("X2")); } return sb.ToString(); } /// <summary> /// 是否已经存在该程序集 /// </summary> /// <returns>false:不存在该程序集,true:已经存在该程序集</returns> private bool checkCache() { if (File.Exists(this._assPath)) { return true; } return false; } //私有方法,默认取url入口的文件名为类名 private static string getWsclassName(string wsdlUrl) { string[] parts = wsdlUrl.Split('/'); string[] pps = parts[parts.Length - 1].Split('.'); return pps[0]; } #endregion }
]]>
如果你看到了这一篇文章,那么证明你已经安装成功了,感谢使用 Halo 进行创作,希望能够使用愉快。
在使用过程中,有任何问题都可以通过以上链接找寻答案,或者联系我们。
]]>这是一篇自动生成的文章,请删除这篇文章之后开始你的创作吧!