架构师_程序员

查看: 64|回复: 1

[资料] .net/c# 反射非匿名函数 <>f__AnonymousType0 方法

[复制链接]
发表于 2020-10-16 17:51:42 | 显示全部楼层
在使用 aop 面向切面编程的时候,需要把方法设置成虚方法,才能正常拦截方法。由于方法太多,可能会漏写 virtual 关键字,所以使用反射获取所有方法来判断是否漏写关键词。在使用反射获取方法的时候会获取到大量的匿名函数 <>f__AnonymousType0 ,本文利用反射排除匿名方法,获取所有继承泛型基类的对象的所有方法,文本包含.net和.net core版本。

C# 匿名类型(Anonymous Type)学习日记
https://www.itsvse.com/thread-9417-1-1.html


首先获取当前程序集

.net 版本:

  1. public class RuntimeHelper
  2.     {
  3.         /// <summary>
  4.         /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
  5.         /// </summary>
  6.         /// <returns></returns>
  7.         public static IList<Assembly> GetAllAssemblies(string projectName = null)
  8.         {
  9.             var assemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
  10.             if (projectName != null) assemblies = assemblies.Where(x => x.FullName.StartsWith(projectName)).ToList();
  11.             return assemblies;
  12.         }
  13.     }
复制代码


.net core 版本:

  1. public class RuntimeHelper
  2.     {
  3.         /// <summary>
  4.         /// 获取项目程序集,排除所有的系统程序集(Microsoft.***、System.***等)、Nuget下载包
  5.         /// </summary>
  6.         /// <returns></returns>
  7.         public static IList<Assembly> GetAllAssemblies(string projectName = null)
  8.         {
  9.             var list = new List<Assembly>();
  10.             var deps = DependencyContext.Default;
  11.             var libs = deps.CompileLibraries.Where(lib => !lib.Serviceable && lib.Type != "package");//排除所有的系统程序集、Nuget下载包
  12.             if (projectName != null) libs = libs.Where(x => x.Name.StartsWith(projectName));
  13.             foreach (var lib in libs)
  14.             {
  15.                 try
  16.                 {
  17.                     var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName(lib.Name));
  18.                     list.Add(assembly);
  19.                 }
  20.                 catch (Exception)
  21.                 {
  22.                     // ignored
  23.                 }
  24.             }
  25.             return list;
  26.         }
  27.     }
复制代码


服务对象继承的基类

  1. public abstract class BaseService<Entity, IDType> : ServiceLoad<Entity, IDType>, IBaseService<Entity, IDType>
  2.         where Entity : BaseDomainModel<IDType>
  3.         where IDType : struct
  4.                 {
  5.                         ...
  6.                 }
复制代码


反射获取非虚方法

在获取到所有程序集,通过反射获取所有方法的时候,可能会获取到 AnonymousType 匿名方法,如下图:

1023c905-2e30-46de-8fc5-b0894f3cff83.png

.NET 版本

  1. var assemblies = Common.RuntimeHelper.GetAllAssemblies("Itsvse.Service");
  2.                 var calssAll = assemblies.Where(x => x.GetTypes().Any(c => c.IsGenericType && c.GetGenericTypeDefinition().IsAssignableFrom(typeof(BaseService<,>)))).SelectMany(x => x.GetTypes()).Where(x => x.IsAbstract == false && x.Namespace != null && x.DeclaringType == null).ToList();
  3.                 foreach (Type item in calssAll)
  4.                 {
  5.                     var methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).Where(x => x.IsStatic == false && x.IsVirtual == false).ToArray();
  6.                     if (methods.Any())
  7.                     {
  8.                         throw new Exception(string.Join(",", methods.Select(x => x.Name)));
  9.                     }
  10.                 }
复制代码


.NET Core 版本

  1. var assemblies = Common.RuntimeHelper.GetAllAssemblies("itsvse").ToArray();
  2.             var calssAll = assemblies.Where(x => x.GetTypes().Any(c => c.IsGenericType && c.GetGenericTypeDefinition().IsAssignableFrom(typeof(BaseService<,>)))).SelectMany(x => x.GetTypes()).Where(x => x.IsAbstract == false && x.Namespace != null && x.DeclaringType == null).ToList();
  3.             foreach (Type item in calssAll)
  4.             {
  5.                 var methods = item.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly).Where(x => x.IsStatic == false && x.IsVirtual == false).ToArray();
  6.                 if (methods.Any())
  7.                 {
  8.                     throw new Exception(string.Join(',', methods.Select(x => x.Name)));
  9.                 }
  10.             }
复制代码


判断是否是匿名函数

  1. var t = new { a = 2, b = "z" }.GetType();
  2. bool isAnonymous = t.Namespace == null && t.DeclaringType == null;
复制代码


匿名函数的 Namespace 、 DeclaringType 都是为 null 非匿名函数的 Namespace 一定不为 null!




上一篇:C# 匿名类型(Anonymous Type)学习日记
下一篇:使用十年的电脑在家用记事本调试 .NET 程序
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
 楼主| 发表于 2020-10-16 18:02:10 | 显示全部楼层
获取程序集的所有对象的时候,会发现有一些 +<>c 编译器生成的匿名对象
可以通过 CompilerGeneratedAttribute 特性区分编译器生成的对象

代码如下:

  1. Console.WriteLine("by:itsvse.com 小渣渣");
  2.             var mscorlib = Assembly.GetExecutingAssembly();
  3.             var ts = mscorlib.GetTypes();
  4.             ts.ToList().ForEach(x => Console.WriteLine(x.FullName));
  5.             Console.WriteLine(string.Empty.PadLeft(100, '='));
  6.             foreach (var item in ts.Where(x => !string.IsNullOrEmpty(x.Namespace) && x.GetCustomAttributes(typeof(CompilerGeneratedAttribute)).FirstOrDefault() == null).ToList())
  7.             {
  8.                 Console.WriteLine(item.FullName);
  9.             }
  10.             Console.ReadKey();
复制代码
QQ截图20201016180149.jpg
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2020-10-28 17:08

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表