commit 96b8361605c88882ad3e262559f93e94cb1dad0c Author: wangwei <1163568462@qq.com> Date: Thu Aug 27 11:45:35 2026 +0800 上传文件至「/」 diff --git a/MAC8.cs b/MAC8.cs new file mode 100644 index 0000000..8ba641a --- /dev/null +++ b/MAC8.cs @@ -0,0 +1,103 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System; +using System.Data; +using System.Configuration; +using System.Web; +using GThinking.N_MISPRO; +using GThinking.N_MISPROAS.Logging; + + +[assembly: AssemblyTitle("S_XLXSBJ")] // ²¿¼þID£¬Îް汾ºÅ +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("½­ËÕʡ½ð˼άÐÅϢ¼¼ÊõÓÐÏ޹«˾")] +[assembly: AssemblyProduct("½ð˼άÈí¼þ")] +[assembly: AssemblyCopyright("(c) ½­ËÕʡ½ð˼άÐÅϢ¼¼ÊõÓÐÏ޹«˾ °æȨËùÓÐ")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] +// GUID¡£±àºŹæÔò47544950-5333-4e45-5420-xxxxxxxxxxx¡£ǰËĶι̶¨¡£×îºóһ¶ÎΪ²¿¼þID×ַû´®ASCIIÂ룬 +// ²»º¬ƽ̨°汾ºţ¬×6×ֽڣ¬³¬³¤ÐèҪËõд£¬²»×㳤¶Ȳ¹¿ոñ¡£ +[assembly: Guid("47544950-5338-4E45-5420-535F4B435357")] +// ³ÌÐ򼯰汾ÐÅϢ +[assembly: AssemblyVersion("1.0.0.0")] // ¹̶¨Ϊ1.0.0.0 +[assembly: AssemblyFileVersion("8.0.0.0")] // ²¿¼þ°汾 + + +namespace GThinking.S_XLXSBJ +{ + public class Mac : GThinking.N_MISPRO.Mac + { + internal static ILog MacLog; + static Mac() + { + // ע²áÄÄЩϵͳ¡¢¸ú×ٵ½ʲôʱ¼䡣ֻÓе±ǰϵͳµļǼ²ű£´档 + MacLog = LogManager.GetMacLogger("S_XLXSBJ8", "", "2222-12-31"); + } + + public Mac() + { + + // ÒÔÏÂÉèÖøò¿¼þµÄÓйØÐÅϢ + ID = "S_XLXSBJ8"; + ClassID = "S_XLXSBJ"; + Name = "ÏßÀÂÏúÊ۱¨¼۷þÎñ"; + Protocol = "NET"; + OACBVersion = 4; + Version = 8; + DBVersion = 2; + DbExtVersion = 0; + Vendor = "½ð˼άÐÅϢ¼¼ÊõÓÐÏ޹«˾"; + Comment = "±ê׼°æ"; + + // ÒÔÏÂÉèÖø÷ģ¿éµÄÐÅϢ + AddModuleInfo(102373000, 0, "ÏßÀÂÏúÊ۱¨¼Û΢ÐŷþÎñ", "N", typeof(WXXLXSBJService)); + AddAjaxService(102373000, "", typeof(WXXLXSBJService)); + + AddModuleInfo(102373001, 0, "ÏßÀÂÏúÊ۱¨¼۷´À¡Êý¾ݽÓÊշþÎñ", "N", typeof(XLXSBJFKJSService)); + AddAjaxService(102373001, "", typeof(XLXSBJFKJSService)); + + AddModuleInfo(102373002, 0, "ÏßÀÂÏúÊۼ۸ñ±í»ù´¡Êý¾ݽÓÊÕAPI½ӿڷþÎñ", "S", typeof(XLXSJGBJCSJService)); + AddAjaxService(102373002, "", typeof(XLXSJGBJCSJService)); + + AddModuleInfo(102373003, 0, "ÏßÀÂÏúÊ۵÷¼۱í»ù´¡Êý¾ݽÓÊÕAPI½ӿڷþÎñ", "S", typeof(XLXSTJBJCSJService)); + AddAjaxService(102373003, "", typeof(XLXSTJBJCSJService)); + + AddModuleInfo(102373004, 0, "ÏßÀÂÏúÊ۵÷¼ÛÒò×ӻù´¡Êý¾ݽÓÊÕAPI½ӿڷþÎñ", "S", typeof(XLXSTJYZJCSJService)); + AddAjaxService(102373004, "", typeof(XLXSTJYZJCSJService)); + + + AddModuleInfo(102373006, 0, "AIÖúÊֽâÎöҳÃæ·þÎñ", "S", typeof(AIZSJXService)); + AddAjaxService(102373006, "", typeof(AIZSJXService)); + AddModuleInfo(102373007, 0, "AIÖúÊָ½¼þÉϴ«ͬ²½·þÎñ", "S", typeof(AIZSFJSCTBService)); + AddAjaxService(102373007, "", typeof(AIZSFJSCTBService)); + + AddModuleInfo(102373010, 0, "AIÖúÊָ½¼þÉϴ«Ò첽·þÎñ", "S", typeof(AIZSFJSCYBService)); + AddAjaxService(102373010, "", typeof(AIZSFJSCYBService)); + + AddModuleInfo(102373011, 0, "¼۸ñ±íµ¼Èë·þÎñ", "S", typeof(JGBDRService)); + AddAjaxService(102373011, "", typeof(JGBDRService)); + + AddModuleInfo(102373012, 0, "ÏßÀ±¨¼ÛÉî¶ȽâÎöµ¼Èë·þÎñ", "S", typeof(XLBJJXDRService)); + AddAjaxService(102373012, "", typeof(XLBJJXDRService)); + + AddModuleInfo(102373013, 0, "Ͷ±êÊý¾ݿìËÙ¼Èë·þÎñ", "S", typeof(XLBJKSLRService)); + AddAjaxService(102373013, "", typeof(XLBJKSLRService)); + + AddModuleInfo(102373016, 0, "ÏßÀÂÏúÊÛÐÂÅúÁ¿µ÷¼۷þÎñ", "S", typeof(BJDPLTJService)); + AddAjaxService(102373016, "", typeof(BJDPLTJService)); + + AddModuleInfo(102373017, 0, "²ÄÁϳɱ¾²éѯ·þÎñ", "S", typeof(CLCBCXService)); + AddAjaxService(102373017, "", typeof(CLCBCXService)); + + AddModuleInfo(102373018, 0, "±¨¼۲ÄÁÏÇ嵥½ÓÊշþÎñ", "S", typeof(BJCLQDJSService)); + AddAjaxService(102373018, "", typeof(BJCLQDJSService)); + + AddModuleInfo(102373019, 0, "·þÎ񷽷¨²ÎÊýÊý¾ÝÉú³ɷþÎñ", "S", typeof(ServiceMethod)); + AddAjaxService(102373019, "", typeof(ServiceMethod)); + + } + } +} diff --git a/ServiceMethod.cs b/ServiceMethod.cs new file mode 100644 index 0000000..c6facf1 --- /dev/null +++ b/ServiceMethod.cs @@ -0,0 +1,943 @@ +using System; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Reflection; +using System.Text; +using System.Xml.XPath; +using GThinking.N_MISPROAS.Web.AjaxServices; +using GThinking.N_MISPRO.Data; + +namespace GThinking.S_XLXSBJ +{ + /// + /// 服务方法管理相关服务。 + /// + public class ServiceMethod + { + /// + /// 根据传入的 DLL 文件地址,反射获取其中标记了 AjaxMethod 的服务方法信息, + /// 并写入数据库表:SRCMD、SRCMETHOD、SRCMETHODPARAMS、SRCTYPE、SRCPROP。 + /// + /// DLL 文件地址。 + /// 操作结果。 + [AjaxMethod(AuthRequried = false)] + public static Dictionary SaveServiceMethodInfo(string filePath) + { + Dictionary result = new Dictionary(); + TDatabase dberp = null; + + if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath)) + { + result["success"] = false; + result["msg"] = "文件地址不能为空或文件不存在"; + return result; + } + + try + { + dberp = TContextDatabases.GetDatabase("DBERP"); + dberp.BeginTrans(); + + Assembly assembly = Assembly.LoadFrom(filePath); + string macId = Truncate(assembly.GetName().Name, 20); + + // 先删除该部件旧数据 + DeleteOldModuleData(dberp, macId); + + XmlDocHelper xmlDoc = new XmlDocHelper(filePath); + int mdIndex = 0; + Dictionary visitedTypes = new Dictionary(StringComparer.OrdinalIgnoreCase); + + Type[] types = null; + try + { + types = assembly.GetTypes(); + } + catch (ReflectionTypeLoadException ex) + { + types = ex.Types; + } + + if (types == null) + { + dberp.CommitTrans(); + result["success"] = true; + result["msg"] = "未找到可扫描的类型"; + result["macId"] = macId; + return result; + } + + foreach (Type type in types) + { + if (type == null) + continue; + if (!type.IsClass) + continue; + + Dictionary methods = GetServiceMethods(type); + if (methods == null || methods.Count == 0) + continue; + + mdIndex++; + double mdId = (double)mdIndex; + + InsertSRCMD(dberp, macId, mdId, Truncate(type.FullName, 40)); + + foreach (ServiceMethodInfo smi in methods.Values) + { + string methodDesc = xmlDoc.GetMethodSummary(smi.MethodInfo); + string retDesc = xmlDoc.GetMethodReturns(smi.MethodInfo); + + InsertSRCMETHOD( + dberp, + macId, + mdId, + Truncate(smi.MethodName, 32), + Truncate(GetMethodModifiers(smi.MethodInfo), 80), + smi.AuthRequried ? "Y" : "N", + smi.UseHttpGet ? "Y" : "N", + Truncate(methodDesc, 4000), + Truncate(GetTypeDisplayName(smi.ReturnType), 80), + Truncate(retDesc, 1000)); + + if (smi.ParameterList != null) + { + int paramXh = 0; + foreach (ServiceParameterInfo spi in smi.ParameterList) + { + string paramDesc = xmlDoc.GetParameterSummary(smi.MethodInfo, spi.Name); + + InsertSRCMETHODPARAMS( + dberp, + macId, + mdId, + Truncate(smi.MethodName, 32), + (double)paramXh, + Truncate(spi.Name, 32), + Truncate(GetTypeDisplayName(spi.ParameterType), 80), + Truncate(paramDesc, 1000)); + + ReflectType(spi.ParameterType, dberp, visitedTypes, xmlDoc); + paramXh++; + } + } + + ReflectType(smi.ReturnType, dberp, visitedTypes, xmlDoc); + } + } + + dberp.CommitTrans(); + result["success"] = true; + result["msg"] = "扫描完成"; + result["macId"] = macId; + } + catch (Exception ex) + { + if (dberp != null && dberp.InTransaction) + dberp.RollbackTrans(); + + result["success"] = false; + result["msg"] = ex.Message; + } + + return result; + } + + /// + /// 根据 MACID 查询已扫描的服务方法数据。 + /// + /// 服务部件ID(程序集名称)。 + /// 包含各表数据的结果。 + [AjaxMethod(AuthRequried = false)] + public static Dictionary GetServiceMethodData(string macId) + { + Dictionary result = new Dictionary(); + TDatabase dberp = null; + + try + { + dberp = TContextDatabases.GetDatabase("DBERP"); + + result["SRCMD"] = QueryTableByMacId(dberp, "SRCMD", macId); + result["SRCMETHOD"] = QueryTableByMacId(dberp, "SRCMETHOD", macId); + result["SRCMETHODPARAMS"] = QueryTableByMacId(dberp, "SRCMETHODPARAMS", macId); + result["SRCTYPE"] = QueryAll(dberp, "SRCTYPE"); + result["SRCPROP"] = QueryAll(dberp, "SRCPROP"); + result["success"] = true; + result["msg"] = ""; + } + catch (Exception ex) + { + result["success"] = false; + result["msg"] = ex.Message; + } + + return result; + } + + #region 数据库操作 + + private static void DeleteOldModuleData(TDatabase dberp, string macId) + { + string[] tables = new string[] { "SRCMETHODPARAMS", "SRCMETHOD", "SRCMD" }; + TSQL sql = new TSQL(dberp); + foreach (string table in tables) + { + sql.Clear(); + sql.Add("delete from " + table + " where MACID=:pMACID"); + sql.ParamByName("pMACID").Value = macId; + dberp.ExecSQL(sql); + } + } + + private static void DeleteTypeData(TDatabase dberp, string typeFullName) + { + TSQL sql = new TSQL(dberp); + sql.Clear(); + sql.Add("delete from SRCPROP where TYPEFULLNAME=:pTYPEFULLNAME"); + sql.ParamByName("pTYPEFULLNAME").Value = typeFullName; + dberp.ExecSQL(sql); + + sql.Clear(); + sql.Add("delete from SRCTYPE where TYPEFULLNAME=:pTYPEFULLNAME"); + sql.ParamByName("pTYPEFULLNAME").Value = typeFullName; + dberp.ExecSQL(sql); + } + + private static List> QueryTableByMacId(TDatabase dberp, string tableName, string macId) + { + TSQL sql = new TSQL(dberp); + sql.Add("select " + GetTableColumns(tableName) + " from " + tableName + " where MACID=:pMACID"); + sql.ParamByName("pMACID").Value = macId; + DataSet ds = dberp.OpenDataSet(sql); + return DataTableToList(ds.Tables[0]); + } + + private static List> QueryAll(TDatabase dberp, string tableName) + { + TSQL sql = new TSQL(dberp); + sql.Add("select " + GetTableColumns(tableName) + " from " + tableName); + DataSet ds = dberp.OpenDataSet(sql); + return DataTableToList(ds.Tables[0]); + } + + private static string GetTableColumns(string tableName) + { + switch (tableName) + { + case "SRCMD": + return "MACID, MDID, MDNAME"; + case "SRCMETHOD": + return "MACID, MDID, METHODNAME, MODIFIERS, AUTHREQUIRED, USEHTTPGET, METHODDESC, RETTYPE, RETDESC"; + case "SRCMETHODPARAMS": + return "MACID, MDID, METHODNAME, PARAMXH, PARAMNAME, PARAMTYPE, PARAMDESC"; + case "SRCTYPE": + return "TYPEFULLNAME, NAMESPACE, TYPENAME, TYPEDESC"; + case "SRCPROP": + return "TYPEFULLNAME, PROPNAME, PROPTYPEFULLNAME, NAMESPACE, PROPTYPE, PROPDESC"; + default: + return "*"; + } + } + + private static List> DataTableToList(DataTable dt) + { + List> list = new List>(); + foreach (DataRow row in dt.Rows) + { + Dictionary item = new Dictionary(); + foreach (DataColumn col in dt.Columns) + { + object val = row[col]; + item[col.ColumnName] = val == DBNull.Value ? null : val; + } + list.Add(item); + } + return list; + } + + private static void InsertSRCMD(TDatabase dberp, string macId, double mdId, string mdName) + { + TSQL sql = new TSQL(dberp); + sql.Clear(); + sql.Add("insert into SRCMD(MACID, MDID, MDNAME) values(:pMACID, :pMDID, :pMDNAME)"); + sql.ParamByName("pMACID").Value = macId; + sql.ParamByName("pMDID").Value = mdId; + sql.ParamByName("pMDNAME").Value = mdName; + dberp.ExecSQL(sql); + } + + private static void InsertSRCMETHOD(TDatabase dberp, string macId, double mdId, string methodName, + string modifiers, string authRequired, string useHttpGet, string methodDesc, + string retType, string retDesc) + { + TSQL sql = new TSQL(dberp); + sql.Clear(); + sql.Add("insert into SRCMETHOD(MACID, MDID, METHODNAME, MODIFIERS, AUTHREQUIRED, USEHTTPGET, METHODDESC, RETTYPE, RETDESC) "); + sql.Add("values(:pMACID, :pMDID, :pMETHODNAME, :pMODIFIERS, :pAUTHREQUIRED, :pUSEHTTPGET, :pMETHODDESC, :pRETTYPE, :pRETDESC)"); + sql.ParamByName("pMACID").Value = macId; + sql.ParamByName("pMDID").Value = mdId; + sql.ParamByName("pMETHODNAME").Value = methodName; + sql.ParamByName("pMODIFIERS").Value = modifiers; + sql.ParamByName("pAUTHREQUIRED").Value = authRequired; + sql.ParamByName("pUSEHTTPGET").Value = useHttpGet; + sql.ParamByName("pMETHODDESC").Value = methodDesc; + sql.ParamByName("pRETTYPE").Value = retType; + sql.ParamByName("pRETDESC").Value = retDesc; + dberp.ExecSQL(sql); + } + + private static void InsertSRCMETHODPARAMS(TDatabase dberp, string macId, double mdId, string methodName, + double paramXh, string paramName, string paramType, string paramDesc) + { + TSQL sql = new TSQL(dberp); + sql.Clear(); + sql.Add("insert into SRCMETHODPARAMS(MACID, MDID, METHODNAME, PARAMXH, PARAMNAME, PARAMTYPE, PARAMDESC) "); + sql.Add("values(:pMACID, :pMDID, :pMETHODNAME, :pPARAMXH, :pPARAMNAME, :pPARAMTYPE, :pPARAMDESC)"); + sql.ParamByName("pMACID").Value = macId; + sql.ParamByName("pMDID").Value = mdId; + sql.ParamByName("pMETHODNAME").Value = methodName; + sql.ParamByName("pPARAMXH").Value = paramXh; + sql.ParamByName("pPARAMNAME").Value = paramName; + sql.ParamByName("pPARAMTYPE").Value = paramType; + sql.ParamByName("pPARAMDESC").Value = paramDesc; + dberp.ExecSQL(sql); + } + + private static void InsertSRCTYPE(TDatabase dberp, string typeFullName, string nameSpace, + string typeName, string typeDesc) + { + TSQL sql = new TSQL(dberp); + sql.Clear(); + sql.Add("insert into SRCTYPE(TYPEFULLNAME, NAMESPACE, TYPENAME, TYPEDESC) "); + sql.Add("values(:pTYPEFULLNAME, :pNAMESPACE, :pTYPENAME, :pTYPEDESC)"); + sql.ParamByName("pTYPEFULLNAME").Value = typeFullName; + sql.ParamByName("pNAMESPACE").Value = nameSpace; + sql.ParamByName("pTYPENAME").Value = typeName; + sql.ParamByName("pTYPEDESC").Value = typeDesc; + dberp.ExecSQL(sql); + } + + private static void InsertSRCPROP(TDatabase dberp, string typeFullName, string propName, + string propTypeFullName, string nameSpace, string propType, string propDesc) + { + TSQL sql = new TSQL(dberp); + sql.Clear(); + sql.Add("insert into SRCPROP(TYPEFULLNAME, PROPNAME, PROPTYPEFULLNAME, NAMESPACE, PROPTYPE, PROPDESC) "); + sql.Add("values(:pTYPEFULLNAME, :pPROPNAME, :pPROPTYPEFULLNAME, :pNAMESPACE, :pPROPTYPE, :pPROPDESC)"); + sql.ParamByName("pTYPEFULLNAME").Value = typeFullName; + sql.ParamByName("pPROPNAME").Value = propName; + sql.ParamByName("pPROPTYPEFULLNAME").Value = propTypeFullName; + sql.ParamByName("pNAMESPACE").Value = nameSpace; + sql.ParamByName("pPROPTYPE").Value = propType; + sql.ParamByName("pPROPDESC").Value = propDesc; + dberp.ExecSQL(sql); + } + + #endregion + + #region 反射与类型辅助 + + private static Dictionary GetServiceMethods(Type classType) + { + if (classType == null) + return null; + + List typeList = new List(); + Type current = classType; + typeList.Add(current); + while (current.BaseType != null) + { + current = current.BaseType; + if (current != typeof(object)) + typeList.Add(current); + } + + Dictionary methods = new Dictionary(StringComparer.OrdinalIgnoreCase); + BindingFlags flags = BindingFlags.Public | BindingFlags.DeclaredOnly | + BindingFlags.Static | BindingFlags.Instance; + + for (int i = typeList.Count - 1; i >= 0; --i) + { + MethodInfo[] methodInfos = typeList[i].GetMethods(flags); + foreach (MethodInfo method in methodInfos) + { + object[] attribs = method.GetCustomAttributes(typeof(AjaxMethodAttribute), true); + if (attribs.Length > 0) + { + AjaxMethodAttribute ajaxAttr = (AjaxMethodAttribute)attribs[0]; + ServiceMethodInfo smi = new ServiceMethodInfo(method, ajaxAttr); + smi.LoadMethodParameters(); + methods[smi.MethodName] = smi; + } + } + } + return methods; + } + + private static string GetMethodModifiers(MethodInfo method) + { + StringBuilder sb = new StringBuilder(); + if (method.IsPublic) + sb.Append("public "); + else if (method.IsPrivate) + sb.Append("private "); + else if (method.IsFamily) + sb.Append("protected "); + else if (method.IsAssembly) + sb.Append("internal "); + + if (method.IsStatic) + sb.Append("static "); + + return sb.ToString().Trim(); + } + + private static void ReflectType(Type type, TDatabase dberp, + Dictionary visitedTypes, XmlDocHelper xmlDoc) + { + if (type == null) + return; + + if (type.IsByRef || type.IsPointer) + { + ReflectType(type.GetElementType(), dberp, visitedTypes, xmlDoc); + return; + } + + if (type.IsArray) + { + ReflectType(type.GetElementType(), dberp, visitedTypes, xmlDoc); + return; + } + + Type underlying = Nullable.GetUnderlyingType(type); + if (underlying != null) + { + ReflectType(underlying, dberp, visitedTypes, xmlDoc); + return; + } + + if (type.IsGenericType) + { + Type[] args = type.GetGenericArguments(); + foreach (Type arg in args) + ReflectType(arg, dberp, visitedTypes, xmlDoc); + + Type def = type.GetGenericTypeDefinition(); + if (!IsCustomType(def)) + return; + + type = def; + } + + if (!IsCustomType(type)) + return; + + string key = type.FullName; + if (string.IsNullOrEmpty(key)) + return; + if (visitedTypes.ContainsKey(key)) + return; + visitedTypes[key] = key; + + string typeFullName = type.FullName.Replace('+', '.'); + + // 先清理该类型旧数据,再重新写入 + DeleteTypeData(dberp, typeFullName); + + InsertSRCTYPE( + dberp, + Truncate(typeFullName, 80), + Truncate(type.Namespace, 80), + Truncate(GetTypeShortName(type), 80), + Truncate(xmlDoc.GetSummary(type), 1000)); + + List members = new List(); + members.AddRange(type.GetProperties(BindingFlags.Public | BindingFlags.Instance)); + members.AddRange(type.GetFields(BindingFlags.Public | BindingFlags.Instance)); + members.Sort(new MemberNameComparer()); + + foreach (MemberInfo mi in members) + { + Type memberType = null; + if (mi is PropertyInfo) + memberType = ((PropertyInfo)mi).PropertyType; + else if (mi is FieldInfo) + memberType = ((FieldInfo)mi).FieldType; + else + continue; + + string propTypeFullName = memberType.FullName == null ? memberType.Name : memberType.FullName.Replace('+', '.'); + + InsertSRCPROP( + dberp, + Truncate(typeFullName, 80), + Truncate(mi.Name, 32), + Truncate(propTypeFullName, 80), + Truncate(memberType.Namespace, 80), + Truncate(GetTypeDisplayName(memberType), 80), + Truncate(xmlDoc.GetSummary(mi), 250)); + + ReflectType(memberType, dberp, visitedTypes, xmlDoc); + } + } + + private static bool IsCustomType(Type type) + { + if (type == null) + return false; + if (type.IsGenericParameter) + return false; + if (type.IsPrimitive) + return false; + if (type == typeof(string) || type == typeof(object) || type == typeof(decimal) + || type == typeof(DateTime) || type == typeof(TimeSpan) || type == typeof(Guid)) + return false; + if (type.Namespace != null && + (type.Namespace.StartsWith("System") || type.Namespace.StartsWith("Microsoft"))) + return false; + return true; + } + + private static string GetTypeDisplayName(Type type) + { + if (type == null) + return ""; + + if (type.IsByRef) + return GetTypeDisplayName(type.GetElementType()) + "&"; + if (type.IsPointer) + return GetTypeDisplayName(type.GetElementType()) + "*"; + if (type.IsArray) + return GetTypeDisplayName(type.GetElementType()) + "[]"; + + Type underlying = Nullable.GetUnderlyingType(type); + if (underlying != null) + return GetTypeDisplayName(underlying) + "?"; + + if (type.IsGenericType) + { + Type def = type.GetGenericTypeDefinition(); + string baseName = def.FullName; + if (string.IsNullOrEmpty(baseName)) + baseName = type.Name; + baseName = baseName.Replace('+', '.'); + int backtick = baseName.IndexOf('`'); + string cleanName = backtick > 0 ? baseName.Substring(0, backtick) : baseName; + + Type[] genericArgs = type.GetGenericArguments(); + StringBuilder sb = new StringBuilder(); + sb.Append(cleanName); + sb.Append("<"); + for (int i = 0; i < genericArgs.Length; i++) + { + sb.Append(GetTypeDisplayName(genericArgs[i])); + if (i < genericArgs.Length - 1) + sb.Append(", "); + } + sb.Append(">"); + return sb.ToString(); + } + + if (type.FullName == null) + return type.Name; + return type.FullName.Replace('+', '.'); + } + + private static string GetTypeShortName(Type type) + { + if (type == null) + return ""; + string name = type.Name; + int backtick = name.IndexOf('`'); + if (backtick > 0) + name = name.Substring(0, backtick); + return name; + } + + private static string Truncate(string value, int maxLength) + { + if (string.IsNullOrEmpty(value)) + return string.Empty; + if (value.Length > maxLength) + return value.Substring(0, maxLength); + return value; + } + + #endregion + + #region 嵌套辅助类 + + /// + /// 服务方法信息。 + /// + private class ServiceMethodInfo + { + internal ServiceMethodInfo(MethodInfo methodInfo, AjaxMethodAttribute methodAttribute) + { + _methodInfo = methodInfo; + _methodName = methodInfo.Name; + _isPublic = methodInfo.IsPublic; + _isStatic = methodInfo.IsStatic; + _returnType = methodInfo.ReturnType; + _authRequried = methodAttribute.AuthRequried; + _useHttpGet = methodAttribute.UseHttpGet; + } + + private MethodInfo _methodInfo; + internal MethodInfo MethodInfo + { + get { return _methodInfo; } + } + + private string _methodName; + public string MethodName + { + get { return _methodName == null ? string.Empty : _methodName; } + set { _methodName = value; } + } + + private bool _isPublic; + public bool IsPublic + { + get { return _isPublic; } + set { _isPublic = value; } + } + + private bool _isStatic; + public bool IsStatic + { + get { return _isStatic; } + set { _isStatic = value; } + } + + private Type _returnType; + public Type ReturnType + { + get { return _returnType; } + set { _returnType = value; } + } + + private bool _authRequried; + public bool AuthRequried + { + get { return _authRequried; } + set { _authRequried = value; } + } + + private bool _useHttpGet; + public bool UseHttpGet + { + get { return _useHttpGet; } + set { _useHttpGet = value; } + } + + private List _parameterList; + public List ParameterList + { + get { return _parameterList; } + set { _parameterList = value; } + } + + internal void LoadMethodParameters() + { + if (_methodInfo == null) + return; + + List list = new List(); + int index = 0; + foreach (ParameterInfo param in _methodInfo.GetParameters()) + { + list.Add(new ServiceParameterInfo(param, index)); + index++; + } + _parameterList = list; + } + } + + /// + /// 服务方法参数信息。 + /// + private class ServiceParameterInfo + { + private ParameterInfo _param; + private int _index; + + internal ServiceParameterInfo(ParameterInfo param, int index) + { + _param = param; + _index = index; + } + + internal ParameterInfo ParameterInfo + { + get { return _param; } + } + + internal int Index + { + get { return _index; } + } + + public string Name + { + get { return _param.Name; } + } + + public Type ParameterType + { + get { return _param.ParameterType; } + } + } + + /// + /// XML 文档注释读取辅助类。 + /// + private class XmlDocHelper + { + private XPathDocument _doc; + private XPathNavigator _nav; + + public XmlDocHelper(string dllPath) + { + if (string.IsNullOrEmpty(dllPath)) + return; + + string fullPath = Path.GetFullPath(dllPath); + string dir = Path.GetDirectoryName(fullPath); + string xmlPath = Path.Combine(dir, Path.GetFileNameWithoutExtension(fullPath) + ".xml"); + if (!File.Exists(xmlPath)) + return; + + try + { + _doc = new XPathDocument(xmlPath); + _nav = _doc.CreateNavigator(); + } + catch + { + _doc = null; + _nav = null; + } + } + + public string GetSummary(Type type) + { + if (_nav == null || type == null) + return ""; + string id = GetTypeDocId(type); + return GetChildText("T", id, "summary"); + } + + public string GetSummary(MemberInfo member) + { + if (_nav == null || member == null) + return ""; + string prefix = "P"; + if (member is FieldInfo) + prefix = "F"; + else if (member is PropertyInfo) + prefix = "P"; + else if (member is MethodInfo) + prefix = "M"; + string id = GetMemberDocId(member); + return GetChildText(prefix, id, "summary"); + } + + public string GetMethodSummary(MethodInfo method) + { + XPathNavigator node = FindMethodNode(method); + if (node == null) + return ""; + XPathNavigator sum = node.SelectSingleNode("summary"); + return sum == null ? "" : sum.Value.Trim(); + } + + public string GetMethodReturns(MethodInfo method) + { + XPathNavigator node = FindMethodNode(method); + if (node == null) + return ""; + XPathNavigator ret = node.SelectSingleNode("returns"); + return ret == null ? "" : ret.Value.Trim(); + } + + public string GetParameterSummary(MethodInfo method, string paramName) + { + XPathNavigator node = FindMethodNode(method); + if (node == null || string.IsNullOrEmpty(paramName)) + return ""; + string expr = "param[@name='" + Escape(paramName) + "']"; + XPathNavigator pn = node.SelectSingleNode(expr); + return pn == null ? "" : pn.Value.Trim(); + } + + private string GetChildText(string prefix, string id, string childName) + { + if (_nav == null) + return ""; + string expr = "//member[@name='" + prefix + ":" + Escape(id) + "']"; + XPathNavigator node = _nav.SelectSingleNode(expr); + if (node == null) + return ""; + XPathNavigator child = node.SelectSingleNode(childName); + return child == null ? "" : child.Value.Trim(); + } + + private XPathNavigator FindMethodNode(MethodInfo method) + { + if (_nav == null || method == null) + return null; + + string exactId = GetMethodDocId(method); + string expr = "//member[@name='M:" + Escape(exactId) + "']"; + XPathNavigator node = _nav.SelectSingleNode(expr); + if (node != null) + return node; + + string typeId = GetTypeDocId(method.DeclaringType); + string prefix = "M:" + Escape(typeId) + "." + method.Name; + XPathNodeIterator iter = _nav.Select("//member[starts-with(@name,'" + prefix + "')]"); + int pCount = method.GetParameters().Length; + + while (iter.MoveNext()) + { + string name = iter.Current.GetAttribute("name", ""); + int open = name.IndexOf('('); + int close = name.LastIndexOf(')'); + if (open > 0 && close > open) + { + string sig = name.Substring(open + 1, close - open - 1); + int count = string.IsNullOrEmpty(sig) ? 0 : CountChar(sig, ',') + 1; + if (count == pCount) + return iter.Current.Clone(); + } + } + return null; + } + + private static string GetTypeDocId(Type type) + { + if (type == null) + return ""; + string fullName = type.FullName; + if (string.IsNullOrEmpty(fullName)) + return type.Name; + return fullName.Replace('+', '.'); + } + + private static string GetMemberDocId(MemberInfo member) + { + Type type = member.DeclaringType; + string typeId = GetTypeDocId(type); + if (member is MethodInfo) + return GetMethodDocId((MethodInfo)member); + return typeId + "." + member.Name; + } + + private static string GetMethodDocId(MethodInfo method) + { + StringBuilder sb = new StringBuilder(); + sb.Append(GetTypeDocId(method.DeclaringType)); + sb.Append("."); + sb.Append(method.Name); + if (method.IsGenericMethod) + sb.Append("``").Append(method.GetGenericArguments().Length); + sb.Append("("); + ParameterInfo[] ps = method.GetParameters(); + for (int i = 0; i < ps.Length; i++) + { + if (i > 0) + sb.Append(","); + sb.Append(GetParameterDocTypeName(ps[i].ParameterType)); + } + sb.Append(")"); + return sb.ToString(); + } + + private static string GetParameterDocTypeName(Type type) + { + if (type == null) + return ""; + if (type.IsGenericParameter) + return type.Name; + if (type.IsByRef) + return GetParameterDocTypeName(type.GetElementType()) + "@"; + if (type.IsPointer) + return GetParameterDocTypeName(type.GetElementType()) + "*"; + if (type.IsArray) + return GetParameterDocTypeName(type.GetElementType()) + "[]"; + + Type underlying = Nullable.GetUnderlyingType(type); + if (underlying != null) + return GetParameterDocTypeName(underlying) + "?"; + + if (type.IsGenericType) + { + Type def = type.GetGenericTypeDefinition(); + string baseName = def.FullName; + if (string.IsNullOrEmpty(baseName)) + baseName = type.Name; + baseName = baseName.Replace('+', '.'); + Type[] args = type.GetGenericArguments(); + StringBuilder sb = new StringBuilder(); + sb.Append(baseName); + sb.Append("{"); + for (int i = 0; i < args.Length; i++) + { + if (i > 0) + sb.Append(","); + sb.Append(GetParameterDocTypeName(args[i])); + } + sb.Append("}"); + return sb.ToString(); + } + + string name = type.FullName; + if (string.IsNullOrEmpty(name)) + name = type.Name; + return name.Replace('+', '.'); + } + + private static string Escape(string s) + { + if (s == null) + return ""; + return s.Replace("'", "''"); + } + + private static int CountChar(string s, char c) + { + int count = 0; + for (int i = 0; i < s.Length; i++) + { + if (s[i] == c) + count++; + } + return count; + } + } + + /// + /// 按成员名称排序的比较器。 + /// + private class MemberNameComparer : IComparer + { + public int Compare(MemberInfo x, MemberInfo y) + { + return string.Compare(x.Name, y.Name, StringComparison.OrdinalIgnoreCase); + } + } + + #endregion + } +} diff --git a/ServiceMethodTables.sql b/ServiceMethodTables.sql new file mode 100644 index 0000000..37f6fa0 --- /dev/null +++ b/ServiceMethodTables.sql @@ -0,0 +1,103 @@ +-- ============================================================ +-- 服务方法管理数据表建表脚本(Oracle) +-- 数据来源:服务方法管理数据表.docx +-- 注意:原文档中参数表名为 SRCPARAMS,已按最新要求改为 SRCMETHODPARAMS +-- ============================================================ + +-- 1. 服务模块表:记录被扫描 DLL 中的类(AjaxMethod 方法所在的类) +CREATE TABLE SRCMD ( + MACID CHAR(20) NOT NULL, -- 服务部件ID(程序集名称) + MDID FLOAT NOT NULL, -- 服务模块号(类序号) + MDNAME CHAR(40) NULL, -- 服务模块名称(类全名) + CONSTRAINT PK_SRCMD PRIMARY KEY (MACID, MDID) +); + +COMMENT ON TABLE SRCMD IS '代码扫描服务模块'; +COMMENT ON COLUMN SRCMD.MACID IS '服务部件ID'; +COMMENT ON COLUMN SRCMD.MDID IS '服务模块号'; +COMMENT ON COLUMN SRCMD.MDNAME IS '服务模块名称'; + +-- 2. 服务方法表:记录类中标记了 AjaxMethod 的方法 +CREATE TABLE SRCMETHOD ( + MACID CHAR(20) NOT NULL, -- 服务部件ID + MDID FLOAT NOT NULL, -- 服务模块号 + METHODNAME CHAR(32) NOT NULL, -- 服务方法名 + MODIFIERS VARCHAR2(80) NULL, -- 方法修饰符(例如 public static) + AUTHREQUIRED CHAR(1) NULL, -- 是否需要登录才能调用(Y/N) + USEHTTPGET CHAR(1) NULL, -- 是否支持 Http GET 调用(Y/N) + METHODDESC VARCHAR2(4000) NULL, -- 服务方法功能描述() + RETTYPE VARCHAR2(80) NULL, -- 返回值类型(包含命名空间) + RETDESC VARCHAR2(1000) NULL, -- 返回值描述() + CONSTRAINT PK_SRCMETHOD PRIMARY KEY (MACID, MDID, METHODNAME) +); + +COMMENT ON TABLE SRCMETHOD IS '代码扫描服务方法'; +COMMENT ON COLUMN SRCMETHOD.MACID IS '服务部件ID'; +COMMENT ON COLUMN SRCMETHOD.MDID IS '服务模块号'; +COMMENT ON COLUMN SRCMETHOD.METHODNAME IS '服务方法名'; +COMMENT ON COLUMN SRCMETHOD.MODIFIERS IS '方法修饰符'; +COMMENT ON COLUMN SRCMETHOD.AUTHREQUIRED IS '是否需要登录才能调用'; +COMMENT ON COLUMN SRCMETHOD.USEHTTPGET IS '是否支持Http GET调用'; +COMMENT ON COLUMN SRCMETHOD.METHODDESC IS '方法功能描述'; +COMMENT ON COLUMN SRCMETHOD.RETTYPE IS '返回值类型'; +COMMENT ON COLUMN SRCMETHOD.RETDESC IS '返回值描述'; + +-- 3. 服务方法参数表:记录每个方法的参数 +CREATE TABLE SRCMETHODPARAMS ( + MACID CHAR(20) NOT NULL, -- 服务部件ID + MDID FLOAT NOT NULL, -- 服务模块号 + METHODNAME CHAR(32) NOT NULL, -- 服务方法名 + PARAMXH FLOAT NOT NULL, -- 参数序号 + PARAMNAME CHAR(32) NULL, -- 参数名 + PARAMTYPE VARCHAR2(80) NULL, -- 参数类型(包含命名空间) + PARAMDESC VARCHAR2(1000) NULL, -- 参数描述() + CONSTRAINT PK_SRCMETHODPARAMS PRIMARY KEY (MACID, MDID, METHODNAME, PARAMXH) +); + +COMMENT ON TABLE SRCMETHODPARAMS IS '代码扫描服务方法参数'; +COMMENT ON COLUMN SRCMETHODPARAMS.MACID IS '服务部件ID'; +COMMENT ON COLUMN SRCMETHODPARAMS.MDID IS '服务模块号'; +COMMENT ON COLUMN SRCMETHODPARAMS.METHODNAME IS '服务方法名'; +COMMENT ON COLUMN SRCMETHODPARAMS.PARAMXH IS '参数序号'; +COMMENT ON COLUMN SRCMETHODPARAMS.PARAMNAME IS '参数名'; +COMMENT ON COLUMN SRCMETHODPARAMS.PARAMTYPE IS '参数类型'; +COMMENT ON COLUMN SRCMETHODPARAMS.PARAMDESC IS '参数描述'; + +-- 4. 数据类型表:记录自定义类型(参数/返回值中用到的自定义类) +CREATE TABLE SRCTYPE ( + TYPEFULLNAME VARCHAR2(80) NOT NULL, -- 类型全称,例如 GThinking.S_XSDD.SOXXData + NAMESPACE VARCHAR2(80) NULL, -- 命名空间 + TYPENAME VARCHAR2(80) NULL, -- 显示名称,例如 SOXXData + TYPEDESC VARCHAR2(1000) NULL, -- 类型描述() + CONSTRAINT PK_SRCTYPE PRIMARY KEY (TYPEFULLNAME) +); + +COMMENT ON TABLE SRCTYPE IS '代码扫描数据类型'; +COMMENT ON COLUMN SRCTYPE.TYPEFULLNAME IS '类型全称'; +COMMENT ON COLUMN SRCTYPE.NAMESPACE IS '命名空间'; +COMMENT ON COLUMN SRCTYPE.TYPENAME IS '显示名称'; +COMMENT ON COLUMN SRCTYPE.TYPEDESC IS '类型描述'; + +-- 5. 数据类型属性表:记录自定义类型的公共属性/字段 +CREATE TABLE SRCPROP ( + TYPEFULLNAME VARCHAR2(80) NOT NULL, -- 类型全称 + PROPNAME CHAR(32) NOT NULL, -- 属性名称 + PROPTYPEFULLNAME VARCHAR2(80) NOT NULL, -- 属性类型全称 + NAMESPACE VARCHAR2(80) NULL, -- 属性类型命名空间 + PROPTYPE VARCHAR2(80) NULL, -- 属性类型显示名称 + PROPDESC VARCHAR2(250) NULL, -- 属性描述() + CONSTRAINT PK_SRCPROP PRIMARY KEY (TYPEFULLNAME, PROPNAME, PROPTYPEFULLNAME) +); + +COMMENT ON TABLE SRCPROP IS '代码扫描数据类型属性'; +COMMENT ON COLUMN SRCPROP.TYPEFULLNAME IS '类型全称'; +COMMENT ON COLUMN SRCPROP.PROPNAME IS '属性名称'; +COMMENT ON COLUMN SRCPROP.PROPTYPEFULLNAME IS '属性类型全称'; +COMMENT ON COLUMN SRCPROP.NAMESPACE IS '属性类型命名空间'; +COMMENT ON COLUMN SRCPROP.PROPTYPE IS '属性类型'; +COMMENT ON COLUMN SRCPROP.PROPDESC IS '属性描述'; + +-- 可选索引:加速按 MACID 查询 +CREATE INDEX IDX_SRCMETHOD_MACID ON SRCMETHOD(MACID); +CREATE INDEX IDX_SRCMETHODPARAMS_MACID ON SRCMETHODPARAMS(MACID); +CREATE INDEX IDX_SRCPROP_TYPEFULLNAME ON SRCPROP(TYPEFULLNAME); diff --git a/ServiceMethodView.html b/ServiceMethodView.html new file mode 100644 index 0000000..1aa9b43 --- /dev/null +++ b/ServiceMethodView.html @@ -0,0 +1,808 @@ + + + + + + 服务方法管理 - DLL 扫描浏览 + + + + + + + + + + + +
+
+
+

服务方法管理 — DLL 扫描浏览

+
+ + + + 最近路径 + + {{ p }} + 清空记录 + + + + 扫描 DLL + + + 刷新数据 + +
+
+ +
+
+ 服务部件 + {{ macId }} +
+
+ 模块数 + {{ srcmd.length }} +
+
+ 方法数 + {{ srcmethod.length }} +
+
+ 参数数 + {{ srcmethodparams.length }} +
+
+ 自定义类型 + {{ srctype.length }} +
+
+ +
+ + + + + + + + 清空筛选 + + 按模块浏览 + 按类型浏览 + + {{ filteredMethodCount }} 个方法 +
+ +
+ +
+ + + + + +
+ +
+ + + +
{{ currentTypeNamespace }}
+
{{ currentTypeDesc }}
+
公共属性 / 字段({{ currentTypeProps.length }})
+
该类型没有公共属性/字段
+
+
+
+ {{ prop.PROPNAME }} + + {{ prop.PROPTYPE || prop.PROPTYPEFULLNAME }} + +
+
{{ prop.PROPDESC }}
+
+
+
+ +
+ +
输入 DLL 文件路径并点击“扫描 DLL”开始解析服务方法
+
+
+
+ + + +