public void ParseTest() { EnumContract ec = EnumContract.Parse("StatusCode", "服务器响应码(short 3.2-2.6.9)", "short=>{Exception:-1/*服务器异常*/, Success:0/*服务器处理成功*/, Updatable:1/*主程序有更新 请按照客户端更新策略下载*/}"); Console.WriteLine(ec.Definition.Length); }
/// <summary> /// 在当前上下文中写入已知类型数据,并移动上下文写入游标索引。 /// </summary> /// <param name="context">当前字节序列上下文</param> /// <param name="writer">二进制写入器</param> /// <param name="dType">规范数据定义</param> /// <param name="objData">写入对象实例</param> /// <param name="isNetworkBytes">是否写入网络序</param> public static void WriteKnownTypeObject(StreamContext context, BinaryWriter writer, SpecDataType dType, object objData, bool isNetworkBytes) { Type clrType = dType.GetRuntimeType(); if (dType.Prototype == SpecDataPrototype.Native) { context.IncreasePosition(SpecData.CLRObjectWrite(clrType, writer, objData, isNetworkBytes)); } else { if (dType.Prototype == SpecDataPrototype.Array) { Type elementType = dType.GetElementType(); Array arrObj = (Array)objData; if (SpecDataType.IsNativeType(TypeCache.ToSimpleType(elementType))) { #region 写入基础数据类型数组 for (int i = 0, j = dType.ElementLength; i < j; i++) { context.IncreasePosition(SpecData.CLRObjectWrite(elementType, writer, arrObj.GetValue(i), isNetworkBytes)); } #endregion } else { for (int m = 0, n = dType.ElementLength; m < n; m++) { WriteKnownTypeObject(context, writer, dType.GetElementDataType(), arrObj.GetValue(m), isNetworkBytes); } } } else { #region 扩展写入 if (clrType.Equals(typeof(EnumContract))) { EnumContract enc = (EnumContract)dType.GetDefineInstance(); clrType = enc.GetBaseRuntimeType(); if (!objData.GetType().Equals(clrType)) { objData = enc.GetEnumUnderlyingValue(objData.ToString()); } context.IncreasePosition(SpecData.CLRObjectWrite(clrType, writer, objData, isNetworkBytes)); } else if (clrType.Equals(typeof(DataContract))) { DataContract dac = (DataContract)dType.GetDefineInstance(); WriteByContract(context, writer, (Dictionary <string, object>)objData, dac); } else { throw new SpecDataDefineException(string.Format("不能读取数据类型{0}!", clrType.FullName)); } #endregion } } }
/// <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="name">枚举定义名称</param> /// <param name="description">枚举定义描述</param> /// <param name="defRaw">原始定义字符串</param> /// <returns></returns> public static EnumContract Parse(string name, string description, string defRaw) { EnumContract enc = new EnumContract(); //EaseSuccessFlag = short=>{Error:-1, UnKnown:0, Success:1010, SuccessUserAgent:1020, SuccessExpress:1120} //#服务器响应码(short 3.2-2.6.9) //StatusCode=short=>{Exception:-1/*服务器异常*/, Success:0/*服务器处理成功*/, Updatable:1/*主程序有更新,请按照客户端更新策略下载*/} enc.TypeName = name; enc.Description = description; int idx = defRaw.IndexOf("=>"); if (idx == -1) { throw new SpecDataDefineException("没有找到枚举数据类型定义的分隔标识符号:'=>'!"); } enc.BaseType = defRaw.Substring(0, idx).Trim(); string itemDefExp = defRaw.Substring(idx + 2).Trim().Trim('{', '}'); #region 最简定义解析 string[] itemArr = itemDefExp.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); string key = null, value = null; foreach (string item in itemArr) { idx = item.IndexOf(':'); if (idx == -1) { continue; } else { key = item.Substring(0, idx).Trim(); value = item.Substring(idx + 1); //检查是否包含注释 idx = value.IndexOf('/'); if (idx == -1) { enc.SetEnumItem(key, value); } else { enc[key] = new DataItem { DataName = key, ItemValue = value.Substring(0, idx).Trim(), Description = value.Substring(idx).Trim('/', '*') }; } } } #endregion #region 灵活定义解析 //using (StringParseHelper dep = new StringParseHelper(itemDefExp)) //{ // //{Exception:-1/*服务器异常*/, Success:0/*服务器处理成功*/, Updatable:1/*主程序有更新,请按照客户端更新策略下载*/} // /* // * when found : => getBufferAsKey -> readToChar([',','}']) -> getBufferAsValue // * when found / => checkNextCharIs('*') -> readToChar(['*']) and peekNextChar == '/' as Key Comment // * // */ // dep.Parse(); //} #endregion return(enc); }
/// <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> /// 解析数据类型 /// </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> /// 在当前上下文中读取已知类型读取数据,并移动上下文读取游标索引。 /// </summary> /// <param name="context">当前字节序列上下文</param> /// <param name="reader">二进制读取器</param> /// <param name="dType">规范数据定义</param> /// <returns></returns> public static object ReadKnownTypeObject(StreamContext context, BinaryReader reader, SpecDataType dType) { object itemObj = null; Type clrType = dType.GetRuntimeType(); if (dType.Prototype == SpecDataPrototype.Native) { itemObj = SpecData.CLRObjectFromReader(clrType, reader); context.IncreasePosition(SpecData.GetCLRTypeByteLength(clrType)); } else { if (dType.Prototype == SpecDataPrototype.Array) { Type elementType = dType.GetElementType(); Array arrObj = Array.CreateInstance(elementType, dType.ElementLength); if (SpecDataType.IsNativeType(TypeCache.ToSimpleType(elementType))) { #region 读取基础数据类型数组 long unitLen = SpecData.GetCLRTypeByteLength(elementType); for (int i = 0, j = dType.ElementLength; i < j; i++) { arrObj.SetValue(SpecData.CLRObjectFromReader(elementType, reader), i); context.IncreasePosition(unitLen); } #endregion } else { for (int m = 0, n = dType.ElementLength; m < n; m++) { arrObj.SetValue(ReadKnownTypeObject(context, reader, dType.GetElementDataType()), m); } } itemObj = arrObj; } else { #region 扩展读取 if (clrType.Equals(typeof(EnumContract))) { EnumContract enc = (EnumContract)dType.GetDefineInstance(); clrType = enc.GetBaseRuntimeType(); itemObj = SpecData.CLRObjectFromReader(clrType, reader); context.IncreasePosition(SpecData.GetCLRTypeByteLength(clrType)); } else if (clrType.Equals(typeof(DataContract))) { DataContract dac = (DataContract)dType.GetDefineInstance(); itemObj = ReadByContract(context, reader, dac); } else { throw new SpecDataDefineException(string.Format("不能读取数据类型{0}!", clrType.FullName)); } #endregion } } return(itemObj); }