ABP基于Attribute构建动态Api

背景

加的群里有人(这里暂且成为A君)有这样的需求:针对PC端和App端有不同的api需求,例如App端只可访问GetXXX,而PC端可访问GetXXX,UpdateXXX,CreateXXX等。

而我们也知道,Abp中是提供了这样的方法的,但写起来比较麻烦,写法如下:

1 DynamicApiControllerBuilder
2     .For<ITaskAppService>("tasksystem/task")
3     .ForMethod("CreateTask").DontCreateAction()
4     .ForMethod("UpdateTask").DontCreateAction()
5     .ForMethod("DeleteTask").DontCreateAction()
6     .Build();

于是A君通过反射和Attribute相结合自己实现了一套,但遇到了些问题,于是在讨论的过程中我也试着在本机测试了下,最终测试通过,下面给出解决方案。

解决方案

1.定义一个Attribute,这个Attribute里边没什么代码,只是标识作用。

1 public class AppUsedAttribute : Attribute
2 {
3 }

2.实现类

 1 public class BuildApiHelper
 2     {
 3         public static void BuildApi(Type moduleType, string servicePrefix, Type attrType)
 4         {
 5             var _assembly = Assembly.GetAssembly(moduleType);
 6 
 7             var types = from type in _assembly.GetTypes()
 8                         where type.IsPublic &&
 9                               type.IsInterface && typeof(IApplicationService).IsAssignableFrom(type) &&
10                               IocManager.Instance.IsRegistered(type)
11                         select type;
12 
13             foreach (var type in types)
14             {
15                 var serviceName = servicePrefix + "/" + GetConventionalServiceName(type);
16 
17                 var obj = typeof(DynamicApiControllerBuilder)
18                     .GetMethod("For", BindingFlags.Public | BindingFlags.Static)
19                     .MakeGenericMethod(type)
20                     .Invoke(null, new object[] { serviceName });
21 
22                 var methods = type.GetMethods().Where(n => n.DeclaringType == type).ToArray();
23 
24                 foreach (MethodInfo item in methods)
25                 {
26                     var attr = item.GetCustomAttribute(attrType);
27                     if (attr == null)
28                     {
29                         var ationobj = obj.GetType().GetMethod("ForMethod").Invoke(obj, new object[] { item.Name });
30                         obj = ationobj.GetType().GetMethod("DontCreateAction").Invoke(ationobj, null);
31                     }
32                 }
33                 obj.GetType().GetMethod("Build").Invoke(obj, null);
34             }
35         }
36 
37         private static string GetConventionalServiceName(Type type)
38         {
39             var typeName = type.Name;
40 
41             if (typeName.EndsWith("ApplicationService"))
42             {
43                 typeName = typeName.Substring(0, typeName.Length - "ApplicationService".Length);
44             }
45             else if (typeName.EndsWith("AppService"))
46             {
47                 typeName = typeName.Substring(0, typeName.Length - "AppService".Length);
48             }
49             else if (typeName.EndsWith("Service"))
50             {
51                 typeName = typeName.Substring(0, typeName.Length - "Service".Length);
52             }
53 
54             if (typeName.Length > 1 && typeName.StartsWith("I") && char.IsUpper(typeName, 1))
55             {
56                 typeName = typeName.Substring(1);
57             }
58 
59             return typeName.ToCamelCase();
60         }
61     }

3.调用方式

1 public override void Initialize()
2 { 
3      IocManager.RegisterAssemblyByConvention(Assembly.GetExecutingAssembly());
4 
5      BuildApiHelper.BuildApi(typeof(MonkeyApplicationModule), "app", typeof(AppUsedAttribute));
6 
7 }

 写在最后

这只是实现方式中的一种解决方案,如何你有更好的解决方案欢迎在评论中指出,欢迎大家一起讨论,共同进步

原文地址:https://www.cnblogs.com/dotnetmonkey/p/abpwebapibasedonattribute.html