/// <summary> /// 加载并解析协议定义文件[TODO] /// </summary> /// <param name="specUrl">协议定义文件地址</param> /// <returns></returns> public static SpecFile ParseContractFile(string specUrl, SpecFileFormat format) { if (format != SpecFileFormat.Ini) { throw new NotSupportedException(); } List <EnumContract> defList = new List <EnumContract>(); List <DataContract> impList = new List <DataContract>(); SpecFile fileDefine = new SpecFile(); using (IniFile ini = new IniFile(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, specUrl))) { fileDefine.FileUrl = ini.Path; fileDefine.FileName = Path.GetFileName(ini.Path); string[] allSecNames = ini.GetSectionNames(); Dictionary <string, string> secDict = new Dictionary <string, string>(); foreach (string secName in allSecNames) { #region 对定义区间解析 if (secName.Equals("define", StringComparison.InvariantCultureIgnoreCase)) { secDict = ini.GetSectionValues(secName); string itemComment = string.Empty; #region 读取枚举定义(define) foreach (var k in secDict.Keys) { itemComment = ini.GetComment(secName, k); defList.Add(EnumContract.Parse(k, itemComment, secDict[k])); } #endregion } else if (secName.Equals("RequestContract", StringComparison.InvariantCultureIgnoreCase)) { fileDefine.RequestContract = ReadAsContract(fileDefine, secName, ini.GetSectionValues(secName), (s, k) => ini.GetComment(s, k), ImportSpecFile); } else if (secName.Equals("ResponseContract", StringComparison.InvariantCultureIgnoreCase)) { fileDefine.ResponseContract = ReadAsContract(fileDefine, secName, ini.GetSectionValues(secName), (s, k) => ini.GetComment(s, k), ImportSpecFile); } else { #region 读取规范导入(import) impList.Add(ReadAsContract(fileDefine, secName, ini.GetSectionValues(secName), (s, k) => ini.GetComment(s, k), ImportSpecFile)); #endregion } #endregion } } fileDefine.MerginDefineWith(defList); fileDefine.MerginImportWith(impList); return(fileDefine); }
/// <summary> /// 导入并合并现有的契约规范定义 /// </summary> /// <param name="srcSpecFile">原始请求规范文件定义</param> /// <param name="specDef">规范文件路径或名称,相对路径。</param> public static void ImportSpecFile(SpecFile srcSpecFile, string specDef) { if (!specDef.EndsWith(".spec")) { specDef += ".spec"; } string impnewFile = Path.Combine(Path.GetDirectoryName(srcSpecFile.FileUrl), specDef); SpecFile newSpec = ParseContractFile(impnewFile, SpecFileFormat.Ini); srcSpecFile.MerginWithSpecFile(newSpec); }
/// <summary> /// 合并导入规范数据 /// </summary> /// <param name="impSpec">规范数据文件实例</param> public void MerginWithSpecFile(SpecFile impSpec) { if (ImportSpecDict.ContainsKey(impSpec.FileUrl)) { return; } else { int i = 0, j = 0; #region 导入枚举定义 if (impSpec.AllDefinition != null && impSpec.AllDefinition.Length > 0) { List <EnumContract> enumList = new List <EnumContract>(); EnumContract current = null; for (i = 0, j = impSpec.AllDefinition.Length; i < j; i++) { current = impSpec.AllDefinition[i]; if (GetDefine(current.TypeName) != null) { continue; } else { enumList.Add(current); } } #region 导入现有定义 if (AllDefinition != null) { enumList.AddRange(AllDefinition); } #endregion AllDefinition = enumList.ToArray(); } #endregion #region 导入数据契约定义 if (impSpec.AllImportContracts != null && impSpec.AllImportContracts.Length > 0) { List <DataContract> impList = new List <DataContract>(); DataContract crtContract = null; for (i = 0, j = impSpec.AllImportContracts.Length; i < j; i++) { crtContract = impSpec.AllImportContracts[i]; if (this[crtContract.ContractName] != null) { continue; } else { impList.Add(crtContract); } } #region 导入现有契约定义 if (AllImportContracts != null) { impList.AddRange(AllImportContracts); } #endregion AllImportContracts = impList.ToArray(); } #endregion ImportSpecDict.Add(impSpec.FileUrl, impSpec); } }
/// <summary> /// [ST:DEBUG]读取配置项词典为数据契约定义 /// </summary> /// <param name="srcSpecFile">原始请求规范文件定义</param> /// <param name="contractName">数据契约名称</param> /// <param name="itemDict">配置项词典</param> /// <param name="cmtHandler">获取项描述的委托</param> /// <param name="importHandler">导入(import)规范委托</param> /// <returns></returns> static DataContract ReadAsContract(SpecFile srcSpecFile, string contractName, Dictionary <string, string> itemDict, DataItemCommentFetchHanlder cmtHandler, ImportSpecFileHandler importHandler) { DataContract contract = new DataContract(); contract.ContractName = contractName; List <DataItem> itemList = new List <DataItem>(); foreach (string key in itemDict.Keys) { if (key.StartsWith("!")) { if (key.Equals("!Compatibility", StringComparison.InvariantCultureIgnoreCase)) { contract.Compatibility = itemDict[key]; } else if (key.Equals("!Compatibility-Reference", StringComparison.InvariantCultureIgnoreCase)) { contract.Compatibility_Reference = itemDict[key]; } else if (key.Equals("!Import", StringComparison.InvariantCultureIgnoreCase)) { if (importHandler != null) { string[] defArr = itemDict[key].Trim().Split(new char[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string impItem in defArr) { importHandler(srcSpecFile, impItem); } } } else if (key.Equals("!base", StringComparison.InvariantCultureIgnoreCase)) { DataContract absDC = srcSpecFile[itemDict[key]]; if (absDC != null && absDC.TransItems != null) { itemList.AddRange(absDC.TransItems); } } continue; } DataItem item = new DataItem(); item.DataName = key; item.NetworkBytes = true; #region 设置数据类型和条件传输表达式 string itemDefine = itemDict[key]; int idx = itemDefine.IndexOf('{'); if (idx == -1) { item.DataType = itemDefine.Trim(); } else { item.DataType = itemDefine.Substring(0, idx).Trim(); item.ConditionalExpression = itemDefine.Substring(idx).Trim(); } #endregion item.Description = cmtHandler(contractName, key); itemList.Add(item); } contract.ConfigItemCount = itemList.Count; contract.TransItems = itemList.ToArray(); return(contract); }
/// <summary> /// 解析数据类型 /// </summary> /// <param name="context">当前解析上下文</param> /// <param name="rawTypeDefine">原始定义字符串</param> /// <returns></returns> public static SpecDataType Parse(StreamContext context, string rawTypeDefine) { SpecDataType sType = new SpecDataType(); sType.TypeName = rawTypeDefine; int idx = -1, idx2 = -1; idx = rawTypeDefine.IndexOf('['); idx2 = rawTypeDefine.IndexOf(']'); if (idx != -1 && idx2 != -1) { if (idx2 - idx == 1) { throw new SpecDataDefineException("数组类型定义[" + rawTypeDefine + "]错误,[]必须包含数据项长度或使用上下文计算的-1!"); } sType.Prototype = SpecDataPrototype.Array; string strTemp = rawTypeDefine.Substring(0, idx); SpecDataType esType = Parse(context, strTemp); sType._elementType = esType.GetRuntimeType(); sType.eleSpecDataType = esType; strTemp = rawTypeDefine.Substring(idx + 1, idx2 - idx - 1).Trim(); if (strTemp == "-1") { DataItem?item = context.GetLastDataItem(); if (!item.HasValue) { throw new SpecDataDefineException("数组类型定义[-1]在上下文中没有前置传输定义项!"); } else { sType.ElementLength = Convert.ToInt32(context.ContextObjectDictionary[item.Value.DataName]); } } else { if (!context.ContextObjectDictionary.ContainsKey(strTemp)) { throw new SpecDataDefineException("数组长度定义[" + strTemp + "]在上下文的没有找到长度定义!"); } else { sType.ElementLength = Convert.ToInt32(context.ContextObjectDictionary[strTemp]); } } sType.SetRuntimeType(sType._elementType.MakeArrayType()); } else { #region 非数组定义 if (IsNativeType(rawTypeDefine)) { sType.Prototype = SpecDataPrototype.Native; sType.SetRuntimeType(TypeCache.GetRuntimeType(rawTypeDefine)); } else { SpecFile specDef = context.ContractSpec; EnumContract enc = TypeCache.FirstOrDefault <EnumContract>(specDef.AllDefinition, d => d.TypeName.Equals(rawTypeDefine)); if (enc != null) { sType.Prototype = SpecDataPrototype.Enum; sType.SetRuntimeType(typeof(EnumContract)); sType.typeDefineInstance = enc; } else { DataContract dac = TypeCache.FirstOrDefault <DataContract>(specDef.AllImportContracts, c => c.ContractName.Equals(rawTypeDefine)); if (dac == null) { throw new SpecDataDefineException("类型定义" + rawTypeDefine + "不能识别!"); } sType.Prototype = SpecDataPrototype.Composite; sType.SetRuntimeType(typeof(DataContract)); sType.typeDefineInstance = dac; } } #endregion } return(sType); }
/// <summary> /// 初始化一个 <see cref="StreamContext"/> class 实例。 /// </summary> /// <param name="spec">当前协议规范定义实例</param> /// <param name="exchangeStream">协议交互共享的字节序列</param> public StreamContext(SpecFile spec, Stream exchangeStream) : this(spec, exchangeStream, exchangeStream) { }
/// <summary> /// 初始化一个 <see cref="StreamContext"/> class 实例。 /// </summary> /// <param name="spec">当前协议规范定义实例</param> /// <param name="readStream">读取字节序列</param> /// <param name="writeStream">写入字节序列</param> public StreamContext(SpecFile spec, Stream readStream, Stream writeStream) { ContractSpec = spec; _reader = new BinaryReader(readStream); _writer = new BinaryWriter(writeStream); }