背景
加的群里有人(这里暂且成为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 }
写在最后
这只是实现方式中的一种解决方案,如何你有更好的解决方案欢迎在评论中指出,欢迎大家一起讨论,共同进步