最近在學習.net core的同時將老師的MVC5項目中的模塊搬過來用,其中有一塊就是利用Attribute來生成菜單。學習
一·首先定義Action實體ui
/// <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類this
/// <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類spa
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中調用,項目啓動時執行方法。.net
public Startup(IConfiguration configuration) { Configuration = configuration; ActionsConfig.GenerateConfigs = true; //是否採用追加模式 ActionsConfig.IsAppendMode = true; //是否修改現有記錄 ActionsConfig.IsModifed = true; ActionsConfig.GetActions(new string[] { "xxx.Controllers"}); }
五.應用。只需在控制器上添加Attribute屬性,就能夠把相應的控制器加入到Action表中。3d
結果如圖code
萌新菜鳥,水平有限,此代碼借鑑了個人老師的項目中的代碼。歡迎各位大佬,批評指正,不吝賜教。blog
QQ:1051599574ip
郵箱:zhangjunx6497@163.comget