最近在学习.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 = ;
}
/// <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>(() => );
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 = ; 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() > ;
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(, 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(, 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 = ; 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() > ;
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(, 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(, 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", );
string areaName = null;
if (areaIndex > )
areaName = nameSections[areaIndex + ];
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