有個項目需要獲取項目內所有Action,併在凌晨定時任務跑完所有介面檢查是否有介面報錯,寫瞭如下方法: /// <summary> /// 獲取Action註釋 /// </summary> /// <param name="root"></param> /// <param name="metho ...
有個項目需要獲取項目內所有Action,併在凌晨定時任務跑完所有介面檢查是否有介面報錯,寫瞭如下方法:
/// <summary> /// 獲取Action註釋 /// </summary> /// <param name="root"></param> /// <param name="method">方法</param> /// <param name="xmlPath">項目xml路徑</param> /// <returns></returns> static string? GetMethodSummary(XmlElement root, MethodInfo method, string xmlPath) { // 查找方法的註釋節點 string memberName = GetMethodSignature(method); XmlNode? memberNode = root.SelectSingleNode($"//member[@name='{memberName}']"); // 獲取方法的 <summary> 註釋 XmlNode? summaryNode = memberNode?.SelectSingleNode("summary"); string? summary = summaryNode?.InnerText.Trim(); return summary; }
/// <summary> /// 獲取控制器註釋 /// </summary> /// <param name="root"></param> /// <param name="controllerType">控制器</param> /// <param name="xmlPath">項目xlm路徑</param> /// <returns></returns> static string? GetMemberSummary(XmlElement root, Type controllerType, string xmlPath) { // 查找方法的註釋節點 string memberName = $"T:{controllerType.FullName}"; XmlNode? memberNode = root.SelectSingleNode($"//member[@name='{memberName}']"); // 獲取方法的 <summary> 註釋 XmlNode? summaryNode = memberNode?.SelectSingleNode("summary"); string? summary = summaryNode?.InnerText.Trim(); return summary; }
/// <summary> /// 獲取方法簽名 /// </summary> /// <param name="methodInfo"></param> /// <returns></returns> static string GetMethodSignature(MethodInfo methodInfo) { StringBuilder signatureBuilder = new StringBuilder(); signatureBuilder.Append($"M:{methodInfo.DeclaringType!.FullName}.{methodInfo.Name}"); ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length > 0) { signatureBuilder.Append("("); for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameter = parameters[i]; // 判斷是否為泛型類型 if (parameter.ParameterType.IsGenericType) { Type genericTypeDefinition = parameter.ParameterType.GetGenericTypeDefinition(); Type[] genericArguments = parameter.ParameterType.GetGenericArguments(); string typeName = $"{genericTypeDefinition.FullName!.Remove(genericTypeDefinition.FullName.IndexOf('`'))}{{"; for (int j = 0; j < genericArguments.Length; j++) { typeName += $"{genericArguments[j].FullName},"; } typeName = typeName.TrimEnd(',') + "}"; signatureBuilder.Append(typeName); } else { signatureBuilder.Append(parameter.ParameterType.FullName); } if (i < parameters.Length - 1) { signatureBuilder.Append(","); } } signatureBuilder.Append(")"); } return signatureBuilder.ToString(); }
實體類:
ublic class Themeinterface { /// <summary> /// 方法 /// </summary> [Description("方法")] [StringLength(50)] [Column("Action")] public string Action { get; set; } /// <summary> /// 方法特性 /// </summary> [Description("方法特性")] [Column("ActionAttributes")] public string? ActionAttributes { get; set; } /// <summary> /// 方法名稱 /// </summary> [Description("方法名稱")] [Column("ActionName")] public string? ActionName { get; set; } /// <summary> /// 方法參數 /// </summary> [Description("方法參數")] [Column("ActionParams")] public string? ActionParams { get; set; } /// <summary> /// 控制器 /// </summary> [Description("控制器")] [StringLength(255)] [Column("Controller")] public string Controller { get; set; } /// <summary> /// 控制器名稱 /// </summary> [Description("控制器名稱")] [Column("ControllerName")] public string? ControllerName { get; set; } [Key] [Column("Id")] public int Id { get; set; } /// <summary> /// 調用時間 /// </summary> [Description("調用時間")] [Column("InvokeTime")] public int? InvokeTime { get; set; } /// <summary> /// 執行狀態 /// </summary> public string Status { get; set; } /// <summary> /// /// </summary> public int StatusCode { get; set; } /// <summary> /// 請求方法 /// </summary> public string? Method { get; set; } /// <summary> /// /// </summary> public string? IP { get; set; } /// <summary> /// 異常 /// </summary> public string? Exception { get; set; } /// <summary> /// 請求路徑 /// </summary> public string? Path { get; set; } /// <summary> /// 請求參數 /// </summary> public string? QueryString { get; set; } /// <summary> /// /// </summary> public DateTime? CreateTime { get; set; } /// <summary> /// /// </summary> public DateTime? UpdateTime { get; set; } }
使用:
/// <summary> /// 獲取所有介面 /// </summary> /// <returns></returns> public static List<Themeinterface> GetAllInterface() { // 獲取方法的 XML 文檔路徑 string xmlPath = Assembly.GetExecutingAssembly().Location.Replace("dll", "xml"); XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(xmlPath); XmlElement root = xmlDoc.DocumentElement!; var childControllers = Assembly.GetExecutingAssembly() .GetTypes() .Where(t => t.IsSubclassOf(typeof(BaseController)) && t != typeof(BaseController) && !t.IsDefined(typeof(IgnoreInterfaceAttribute))) .ToList(); List<Themeinterface> themeinterfaces = new(); foreach (var controllerType in childControllers) { var actions = controllerType.GetMethods(BindingFlags.Public | BindingFlags.Instance) .Where(m => (typeof(IActionResult).IsAssignableFrom(m.ReturnType) || typeof(Task<IActionResult>).IsAssignableFrom(m.ReturnType)) && m.DeclaringType == controllerType && !m.IsDefined(typeof(IgnoreInterfaceAttribute))) .Select(m => new { ActionName = m.Name, Parameters = m.GetParameters() .Select(p => new { Name = p.Name, Type = p.ParameterType.FullName, Attributes = p.GetCustomAttributes().Select(attr => attr.GetType().Name).ToList() }) .ToList(), ActionSummary = GetMethodSummary(root, m, xmlPath), Method = m.GetCustomAttributes(typeof(HttpPostAttribute), false).Cast<HttpPostAttribute>().FirstOrDefault() == null ? "GET" : "POST" }) .ToList(); foreach (var action in actions) { Dictionary<string, object> actionAttributes = new(); foreach (var parameter in action.Parameters) { var key = $"{parameter.Type} {parameter.Name}"; if (parameter.Attributes.Any()) { actionAttributes.Add(key, string.Join(", ", parameter.Attributes)); } } themeinterfaces.Add(new Themeinterface { Action = action.ActionName, ActionName = action.ActionSummary, ActionAttributes = JsonConvert.SerializeObject(actionAttributes.Select(p => p.Value)), //ActionParams = string.Join(", ", action.Parameters.Select(p => p.Name)), Controller = controllerType.FullName!, ControllerName = GetMemberSummary(root, controllerType, xmlPath), Method = action.Method }); } } return themeinterfaces; }