net core中怎么获取类的assembly

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了net core中怎么获取类的assembly相关的知识,希望对你有一定的参考价值。

参考技术A net core中怎么获取类的assembly
本题编程思路如下:五个国家名应由一个二维字符数组来处理。然而C语言规定可以把一个二维数组当成多个一维数组处理。 因此本题又可以按五个一维数组处理, 而每一个一维数组就是一个国家名字符串。用字符串比较函数比较各一维数组的大小,并排序,输出结果即可。
编程如下:
main()

char st[20],cs[5][20];
int i,j,p;
printf("input country's name:\n");
for(i=0;i<5;i++)
gets(cs[i]);
printf("\n");
for(i=0;i<5;i++)
p=i;strcpy(st,cs[i]);
for(j=i+1;j<5;j++)
if(strcmp(cs[j],st)<0) p=j;strcpy(st,cs[j]);
if(p!=i)

strcpy(st,cs[i]);
strcpy(cs[i],cs[p]);
strcpy(cs[p],st);

puts(cs[i]);printf("\n");

本程序的第一个for语句中,用gets函数输入五个国家名字符串。上面说过C语言允许把一个二维数组按多个一维数组处理,本程序说明cs[5][20]为二维字符数组,可分为五个一维数组cs[0],cs[1],cs[2],cs[3],cs[4]。因此在gets函数中使用cs[i]是合法的。 在第二个for语句中又嵌套了一个for语句组成双重循环。这个双重循环完成按字母顺序排序的工作。在外层循环中把字符数组cs[i]中的国名字符串拷贝到数组st中,并把下标i赋予P。进入内层循环后,把st与cs[i]以后的各字符串作比较,若有比st小者则把该字符串拷贝到st中,并把其下标赋予p。内循环完成后如p不等于i说明有比cs[i]更小的字符串出现,因此交换cs[i]和st的内容。至此已确定了数组cs的第i号元素的排序值。然后输出该字符串。在外循环全部完成之后即完成全部排序和输出。
7.5 本章小结

.NET Core分析程序集最优美的方法,不用Assembly.LoadFile(),超越ReflectionOnlyLoad

在编写.NET程序的时候,如果需要对一个程序集文件进行分析,我们可以使用Assembly.LoadFile()来加载这个程序集,然后对LoadFile()方法返回的Assembly对象进行进一步的分析。但是Assembly.LoadFile()方法会以执行为目的把程序集加载到程序中,因此它对于被加载的程序集文件有严格的要求,比如,如果被程序集所依赖的程序集不存在,那么LoadFile()会抛出异常,再比如,在.NET Core中加载.NET Framework的程序集,LoadFile()也会抛出异常。如果我们只想分析程序集,但是并不需要执行程序集,那么我们就需要一种单纯地分析程序集文件的方式。

.NET Framework提供了Assembly.ReflectionOnlyLoad()来实现类似的效果,但是这个方法由于依赖于AppDomain,因此在.NET Core中不被支持。微软曾经在实验室项目中提出过一个在.NET Core中实现这个功能的System.Reflection.TypeLoader,但不知道什么原因,没有在.NET Core的正式版中提供这个类。

我们知道,.NET程序集是PE格式的文件,.NET中提供了用来分析PE文件的类PEReader(位于System.Reflection.Metadata这个NuGet包中),因此我们可以用PEReader来分析程序集文件。

在PEReader中,我们可以通过TypeDefinitions获取到程序集中的所有类,我们可以用GetMethods()获取某个类中定义的所有方法。为了提升效率,TypeDefinitions、GetMethods()等成员获得到的对象都是TypeDefinitionHandle、MethodDefinitionHandle等句柄类型的,这些对象只包含地址信息,并不包含类型的名字、方法的名字、方法的参数等详细信息,要获取这些信息,我们需要调用MetadataReader的GetTypeDefinition()、GetMethodDefinition()等方法来获取。如下的代码用来加载一个程序集,并且输出程序集中所有的类型信息以及类型中定义的方法:

//Install-PackageSystem.Reflection.Metadata
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
 
string file =@"E:\\Microsoft.AspNetCore.Components.Web.dll";
using FileStream fileStream =File.OpenRead(file);
using PEReader peReader = newPEReader(fileStream);
if(!peReader.HasMetadata)

   Console.WriteLine($"file doesn't contain CLI metadata.");
   return;

var mdReader =peReader.GetMetadataReader();
if (!mdReader.IsAssembly)

   Console.WriteLine($"file is not an assembly.");
   return;

foreach (var typeHandler inmdReader.TypeDefinitions)

   var typeDef = mdReader.GetTypeDefinition(typeHandler);
   string name = mdReader.GetString(typeDef.Name);
   string nameSpace = mdReader.GetString(typeDef.Namespace);
   Console.WriteLine($"***********nameSpace.name***********");
   foreach (var methodHandler in typeDef.GetMethods())
    
       var methodDef = mdReader.GetMethodDefinition(methodHandler);
       Console.WriteLine(mdReader.GetString(methodDef.Name));
    

       使用PEReader的时候,我们需要先获得XXXHandler,然后再调用MetadataReader获取句柄的详细信息,这样做尽管性能比较高,但是代码比较繁琐,而且在实现某些高级操作的时候比较麻烦。比如,如果我们要获取一个程序集的CustomAttribute信息,PEReader并没有提供比较简单的方法,需要我们对PE格式非常精通,才能编写出来对应的代码。

       我们可以使用AsmResolver.DotNet这个第三方Nuget包来简化程序集文件的读取分析,它是对PEReader的一个高级封装。如下的代码用来加载一个程序集,输出程序集的公司信息,并且输出程序集中所有的类型信息以及类型中定义的方法:

string file =@"E:\\Microsoft.AspNetCore.Components.Web.dll";
var moduleDef =AsmResolver.DotNet.ModuleDefinition.FromFile(file);//用的不是System.Reflection.Metadata命名空间下的ModuleDefinition类
var asmCompanyAttr =moduleDef.Assembly.CustomAttributes.FirstOrDefault(c =>c.Constructor.DeclaringType.FullName =="System.Reflection.AssemblyCompanyAttribute");
var utf8Value =(Utf8String?)asmCompanyAttr.Signature.FixedArguments[0].Element;
var strValue = (string?)utf8Value;
Console.WriteLine($"companyname:strValue");
foreach(var typeDef inmoduleDef.GetAllTypes())

   string name = typeDef.Name;
   string nameSpace = typeDef.Namespace;
   Console.WriteLine($"***********nameSpace.name***********");
   foreach (var methodDef in typeDef.Methods)
    
       Console.WriteLine(methodDef.Name);
    

       总之,如果我们需要分析一个程序集并且要运行其中的代码,我们可以使用Assembly.LoadFile();如果我们不需要运行程序集,只是想分析程序集,那么使用PEReader是更好的选择,当然我们也可以选择对PEReader进行封装的AsmResolver.DotNet这个NuGet包。本文作者杨中科在Zack.Commons这个开源项目中实现“判断一个程序集是否是微软开发的”这个功能的时候就用到了AsmResolver.DotNet,大家可以查看这个项目的GitHub代码仓库来查看源代码。

以上是关于net core中怎么获取类的assembly的主要内容,如果未能解决你的问题,请参考以下文章

我使用 .net core webapi 怎么获取图片并存到本地磁盘去

.NET Core反射获取带有自定义特性的类,通过依赖注入根据Attribute元数据信息调用对应的方法

asp.net core mvc 2中抽象类的模型绑定器

如何在 ASP.NET Core 中保持对象活动?

在 .NET Core 中使用 CQRS 与服务类的冗长任务 [关闭]

请问:ASP.net mvc5和asp.net.core有啥区别呢?在今后的发展中这个前景怎么样?