最近在学习.net core的同时将老师的MVC5项目中的模块搬过来用,其中有一块就是利用Attribute来生成菜单。

一·首先定义Action实体

 /// <summary>
    /// Action
    /// </summary>
    public class Action
    {
        /// <summary>
        /// ActionId
        /// </summary>
        [DisplayName("ActionId")]
        public Guid Id { get; set; }
        /// <summary>
        /// 唯一的名称
        /// </summary>
        [DisplayName("唯一的名称")]
        public string Name { get; set; }
        /// <summary>
        /// 分区
        /// </summary>
        [DisplayName("分区")]
        public string AreaName { get; set; }
        /// <summary>
        /// 控制器
        /// </summary>
        [DisplayName("控制器")]
        public string ControllerName { get; set; }
        /// <summary>
        /// 活动
        /// </summary>
        [DisplayName("活动")]
        public string ActionName { get; set; }
        /// <summary>
        /// 参数
        /// </summary>
        [DisplayName("参数")]
        public string Parameter { get; set; }
        /// <summary>
        /// 文字
        /// </summary>
        [DisplayName("文字")]
        public string Text { get; set; }
        /// <summary>
        /// 叶节点
        /// </summary>
        [DisplayName("叶节点")]
        public bool IsLeaf { get; set; }
        /// <summary>
        /// 显示顺序
        /// </summary>
        [DisplayName("显示顺序")]
        public int Ordinal { get; set; }
        /// <summary>
        /// 是否显示在左侧的导航栏中
        /// </summary>
        [DisplayName("是否显示在左侧的导航栏中")]
        public bool ShowInLeftNavigationBar { get; set; }
        /// <summary>
        /// 图标
        /// </summary>
        [DisplayName("图标")]
        public string IconClass { get; set; }
        /// <summary>
        /// 级次
        /// </summary>
        [DisplayName("级次")]
        public int Depth { get; set; }
        /// <summary>
        /// 是否链接
        /// </summary>
        [DisplayName("是否链接")]
        public bool IsLink { get; set; }
        /// <summary>
        /// 上级名称(采用上级名称而非上级Id是为了方便数据的存入)
        /// </summary>
        [DisplayName("上级名称")]
        public string ParentName { get; set; }
        /// <summary>
        /// 限制角色
        /// </summary>
        [DisplayName("限制角色")]
        public string AllowedRoles { get; set; }

    }

 

二.新建Attribute类

/// <summary>
    /// 方法描述
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class ActionDescriptorAttribute : Attribute
    {/// <summary>
     /// 方法描述
     /// </summary>
     /// <param name="name">名称(必须唯一)</param>
     /// <param name="text">标题</param>
     /// <param name="depth">深度</param>
     /// <param name="ordinal">显示顺序</param>
     /// <param name="isLink">是否显示为链接</param>
     /// <param name="showInLeftNavigationBar">是否显示在左侧的导航栏中</param>
        public ActionDescriptorAttribute(string name, string text, bool isLink, int depth)
        {
            this.Name = name;
            this.Text = text;
            this.IsLink = isLink;
            this.Depth = depth;
            this.IsLeaf = true;
            this.ShowInLeftNavigationBar = true;
            this.Ordinal = 0;
        }
        /// <summary>
        /// 名称(必须唯一)
        /// </summary>
        public string Name { get; set; }
        /// <summary>
        /// 显示的文本
        /// </summary>
        public string Text { get; set; }

        /// <summary>
        /// 图标
        /// </summary>
        public string IconClass { get; set; }

        /// <summary>
        /// 参数
        /// </summary>
        public string Parameter { get; set; }

        /// <summary>
        /// 是否子菜单
        /// </summary>
        public bool IsLeaf { get; set; }

        /// <summary>
        /// 显示顺序
        /// </summary>
        public int Ordinal { get; set; }

        /// <summary>
        /// 是否在左边导航栏显示
        /// </summary>
        public bool ShowInLeftNavigationBar { get; set; }

        /// <summary>
        /// 一级菜单,该值为1,二级菜单,该值为2,依次类推
        /// </summary>
        public int Depth { get; set; }
        /// <summary>
        /// 是否链接
        /// </summary>
        public bool IsLink { get; set; }
        /// <summary>
        /// 上级名称
        /// </summary>
        public string ParentName { get; set; }
    }

三.新建ActionsConfig类

  public class ActionsConfig
    {
        /// <summary>
        /// 是否生成Actions
        /// </summary>
        public static bool GenerateConfigs { get; set; }
        /// <summary>
        /// 是否采用追加模式,如果是追加模式则不删除现有数据
        /// </summary>
        public static bool IsAppendMode { get; set; }
        /// <summary>
        /// 是否更新现有记录
        /// </summary>
        public static bool IsModifed { get; set; }
        public static Task<int> GetActions(string[] namespaces)
        {
            if (!GenerateConfigs) return new Task<int>(() => 0);
            DAL.NoteBookContext db = new DAL.NoteBookContext();
            var types = Assembly.GetExecutingAssembly().GetExportedTypes().Where(t => namespaces.Contains(t.Namespace)).ToArray();
            var actions = new List<DAL.Entities.Action>();
            for (int i = 0; i < types.Length; i++)
            {
                bool isMvcController = types[i].IsSubclassOf(typeof(Controller));
                //bool isApiController = types[i].IsSubclassOf(typeof(ApiController));
                //if (!isMvcController && !isApiController) continue;
                var fullName = types[i].FullName;
                var name = types[i].Name;
                var areaName = GetAreaName(fullName);
                var tAttr = types[i].GetCustomAttribute<Attributes.ActionDescriptorAttribute>();
                var authorize = types[i].GetCustomAttributes<AuthorizeAttribute>();
                string roles = "";
                if (authorize != null)
                    roles = string.Join(",", authorize.Select(a => a.Roles));
                if (null != tAttr)
                {
                    string attrName = tAttr.Name;
                    //如果是追加模式需要判断是否已经存在
                    bool find = db.Actions.Where(a => a.Name == attrName).Count() > 0;
                    if (!IsAppendMode || !find)
                        actions.Add(new DAL.Entities.Action
                        {
                            Id = Guid.NewGuid(),
                            Name = tAttr.Name,
                            Text = tAttr.Text,
                            Parameter = tAttr.Parameter,
                            AreaName = areaName,
                            ControllerName = name.Substring(0, name.IndexOf("Controller")),
                            ActionName = "#",
                            IsLeaf = tAttr.IsLeaf,
                            IconClass = tAttr.IconClass,
                            Ordinal = tAttr.Ordinal,
                            ShowInLeftNavigationBar = true,
                            Depth = tAttr.Depth,
                            ParentName = tAttr.ParentName,
                            IsLink = tAttr.IsLink,
                            AllowedRoles = roles
                        });
                    if (find && IsModifed)
                    {
                        DAL.Entities.Action action = db.Actions.Where(a => a.Name == attrName).FirstOrDefault();
                        action.Text = tAttr.Text;
                        action.Parameter = tAttr.Parameter;
                        action.AreaName = areaName;
                        action.ControllerName = name.Substring(0, name.IndexOf("Controller"));
                        action.ActionName = "#";
                        action.IsLeaf = tAttr.IsLeaf;
                        action.IconClass = tAttr.IconClass;
                        action.Ordinal = tAttr.Ordinal;
                        action.ShowInLeftNavigationBar = true;
                        action.Depth = tAttr.Depth;
                        action.ParentName = tAttr.ParentName;
                        action.IsLink = tAttr.IsLink;
                        action.AllowedRoles = string.IsNullOrEmpty(roles) || roles == "None" ? null : roles;
                        if (string.IsNullOrEmpty(roles) || roles == "None")
                            action.AllowedRoles = null;
                        db.SaveChanges();
                    }
                }
                var methods = types[i].GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance);
                for (int j = 0; j < methods.Length; j++)
                {
                    var mAttr = methods[j].GetCustomAttribute<Attributes.ActionDescriptorAttribute>();
                    if (null != mAttr)
                    {
                        string attrName = mAttr.Name;
                        //如果是追加模式需要判断是否已经存在
                        bool find = db.Actions.Where(a => a.Name == attrName).Count() > 0;
                        if (find && IsModifed)
                        {
                            DAL.Entities.Action action = db.Actions.Where(a => a.Name == attrName).FirstOrDefault();
                            action.Text = mAttr.Text;
                            action.Parameter = mAttr.Parameter;
                            action.AreaName = areaName;
                            action.ControllerName = name.Substring(0, name.IndexOf("Controller"));
                            action.ActionName = methods[j].Name;
                            action.IsLeaf = mAttr.IsLeaf;
                            action.IconClass = mAttr.IconClass;
                            action.Ordinal = mAttr.Ordinal;
                            action.ShowInLeftNavigationBar = mAttr.ShowInLeftNavigationBar;
                            action.Depth = mAttr.Depth;
                            action.ParentName = mAttr.ParentName;
                            action.IsLink = mAttr.IsLink;
                            action.AllowedRoles = string.IsNullOrEmpty(roles) || roles == "None" ? null : roles;
                            if (string.IsNullOrEmpty(roles) || roles == "None")
                                action.AllowedRoles = null;
                            db.SaveChanges();
                        }
                        if (find && IsAppendMode) continue;
                        actions.Add(new DAL.Entities.Action
                        {
                            Id = Guid.NewGuid(),
                            Name = mAttr.Name,
                            Text = mAttr.Text,
                            Parameter = mAttr.Parameter,
                            AreaName = areaName,
                            ControllerName = name.Substring(0, name.IndexOf("Controller")),
                            ActionName = methods[j].Name,
                            IsLeaf = mAttr.IsLeaf,
                            IconClass = mAttr.IconClass,
                            Ordinal = mAttr.Ordinal,
                            ShowInLeftNavigationBar = mAttr.ShowInLeftNavigationBar,
                            Depth = mAttr.Depth,
                            ParentName = mAttr.ParentName,
                            IsLink = mAttr.IsLink,
                            AllowedRoles = roles
                        });
                    }
                }
            }

            var bll = new NoteBookBLL<DAL.Entities.Action>();
            if (IsAppendMode)
                return bll.AddRangeAsync(actions);
            else
                return bll.DeleteAsync(a => true).ContinueWith(task =>
                {
                    return bll.AddRangeAsync(actions).Result;
                });
        }

        private static string GetAreaName(string fullName)
        {
            string[] nameSections = fullName.Split(new char[] { '.' });
            var areaIndex = Array.IndexOf(nameSections, "Areas", 0);
            string areaName = null;
            if (areaIndex > 0)
                areaName = nameSections[areaIndex + 1];
            return areaName;
        }
    }

四.在StartUp中调用,项目启动时执行方法。

   public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
            ActionsConfig.GenerateConfigs = true;
            //是否采用追加模式
            ActionsConfig.IsAppendMode = true;
            //是否修改现有记录
            ActionsConfig.IsModifed = true;
            ActionsConfig.GetActions(new string[] {
                "xxx.Controllers"});
        }

五.应用。只需在控制器上添加Attribute属性,就可以把相应的控制器加入到Action表中。

结果如图

 萌新菜鸟,水平有限,此代码借鉴了我的老师的项目中的代码。欢迎各位大佬,批评指正,不吝赐教。

QQ:1051599574

邮箱:zhangjunx6497@163.com