text: ﻿using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Linq;
  using System.Reflection;
  using Microsoft.AspNetCore.Mvc;
  using Microsoft.AspNetCore.Mvc.ApplicationParts;
  using Microsoft.AspNetCore.Mvc.Controllers;
  using NetModular.Lib.Utils.Core.Attributes;
  
  namespace NetModular.Lib.Utils.Mvc.Helpers
  {
      /// <summary>
      /// MVC帮助类
      /// </summary>
      [Singleton]
      public class MvcHelper
      {
          private List<ControllerDescriptor> _controllerDescriptors;
          private List<ActionDescriptor> _actionDescriptors;
          private readonly ApplicationPartManager _partManager;
          private static readonly object LockObject = new object();
  
          public MvcHelper(ApplicationPartManager partManager)
          {
              _partManager = partManager;
          }
  
          /// <summary>
          /// 获取所有Controller，不包含抽象的类
          /// </summary>
          /// <returns></returns>
          public List<ControllerDescriptor> GetAllController()
          {
              lock (LockObject)
              {
                  if (_controllerDescriptors != null && _controllerDescriptors.Any())
                      return _controllerDescriptors;
  
                  _controllerDescriptors = new List<ControllerDescriptor>();
  
                  var controllerFeature = new ControllerFeature();
                  _partManager.PopulateFeature(controllerFeature);
                  var controllerTypes = controllerFeature.Controllers.ToList();
                  foreach (var typeInfo in controllerTypes)
                  {
                      if (typeInfo.IsAbstract)
                          continue;
  
                      var controller = new ControllerDescriptor
                      {
                          Name = typeInfo.Name.Replace("Controller", ""),
                          TypeInfo = typeInfo
                      };
  
                      var areaAttr = (AreaAttribute)Attribute.GetCustomAttribute(typeInfo, typeof(AreaAttribute));
                      if (areaAttr != null)
                      {
                          controller.Area = areaAttr.RouteValue;
                      }
  
                      var descAttr =
                          (DescriptionAttribute)Attribute.GetCustomAttribute(typeInfo, typeof(DescriptionAttribute));
                      if (descAttr != null && descAttr.Description.NotNull())
                      {
                          controller.Description = descAttr.Description;
                      }
  
                      _controllerDescriptors.Add(controller);
                  }
  
                  return _controllerDescriptors;
              }
          }
  
          /// <summary>
          /// 反射所有的action
          /// </summary>
          /// <returns></returns>
          public List<ActionDescriptor> GetAllAction()
          {
              lock (LockObject)
              {
                  if (_actionDescriptors != null && _actionDescriptors.Any())
                      return _actionDescriptors;
  
                  _actionDescriptors = new List<ActionDescriptor>();
  
                  var controllers = GetAllController();
                  foreach (var controller in controllers)
                  {
                      foreach (var method in controller.TypeInfo.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly))
                      {
                          if (!method.CustomAttributes.Any(m =>
                              m.AttributeType == typeof(HttpGetAttribute)
                              || m.AttributeType == typeof(HttpPostAttribute)
                              || m.AttributeType == typeof(HttpPutAttribute)
                              || m.AttributeType == typeof(HttpOptionsAttribute)
                              || m.AttributeType == typeof(HttpHeadAttribute)
                              || m.AttributeType == typeof(HttpPatchAttribute)
                              || m.AttributeType == typeof(HttpDeleteAttribute)))
                              continue;
  
                          var action = new ActionDescriptor
                          {
                              Controller = controller,
                              MethodInfo = method,
                              Name = method.Name
                          };
  
                          var descAttr = (DescriptionAttribute)Attribute.GetCustomAttribute(method, typeof(DescriptionAttribute));
                          if (descAttr != null && descAttr.Description.NotNull())
                          {
                              action.Description = descAttr.Description;
                          }
  
                          _actionDescriptors.Add(action);
                      }
                  }
  
                  return _actionDescriptors;
              }
          }
      }
  
      /// <summary>
      /// 
      /// </summary>
      public class ControllerDescriptor
      {
          /// <summary>
          /// 区域
          /// </summary>
          public string Area { get; set; }
  
          /// <summary>
          /// 名称
          /// </summary>
          public string Name { get; set; }
  
          /// <summary>
          /// 描述
          /// </summary>
          public string Description { get; set; }
  
          /// <summary>
          /// 类型
          /// </summary>
          public TypeInfo TypeInfo { get; set; }
      }
  
      public class ActionDescriptor
      {
          /// <summary>
          /// 
          /// </summary>
          public ControllerDescriptor Controller { get; set; }
  
          /// <summary>
          /// 名称
          /// </summary>
          public string Name { get; set; }
  
          /// <summary>
          /// 描述
          /// </summary>
          public string Description { get; set; }
  
          /// <summary>
          /// 方法信息
          /// </summary>
          public MethodInfo MethodInfo { get; set; }
      }
  }
  