【C#反射】Assembly
Assembly属性的应用
//获取当前执行代码的程序集
Assembly assem = Assembly.GetExecutingAssembly();
Console.WriteLine($"程序集全名:{assem.FullName}" );
Console.WriteLine($"程序集的版本:{assem.GetName().Version}" );
Console.WriteLine($"程序集位置:{assem.Location}" );
Console.WriteLine($"程序集入口:{assem.EntryPoint}");
Console.WriteLine($"获取用于加载程序集的主机上下文:{assem.HostContext}");
Console.WriteLine($"是否保留在可回收的 AssemblyLoadContext 中:{assem.IsCollectible}");
Console.WriteLine($"CLR 版本的文件夹名:{assem.ImageRuntimeVersion}");
Console.WriteLine($"当前程序集是否在当前进程中动态生成的:{assem.IsDynamic}");
Console.WriteLine($"当前程序集是否以完全信任方式加载:{assem.IsFullyTrusted}");
Console.WriteLine($"当前程序集清单的模块:{assem.ManifestModule}");
Console.WriteLine($"获取包含此程序集中模块的集合:{assem.Modules}");
Console.WriteLine($"程序集被加载到只反射上下文而不是执行上下文中:{assem.ReflectionOnly}");
Console.WriteLine($"CLR 对此程序集强制执行的安全规则集:{assem.SecurityRuleSet}");
Type[] types = assem.GetTypes();
Console.WriteLine("程序集下包含的类型:");
foreach (var item in types)
{ Console.WriteLine($"类:{item.Name}");
}
//输出结果:
//程序集全名:ConsoleApp3, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
//程序集的版本:1.0.0.0
//程序集位置:C:\Users\HP\source\repos\ConsoleApp3\bin\Debug\net5.0\ConsoleApp3.dll
//程序集入口:Void Main(System.String[])
//获取用于加载程序集的主机上下文:0
//是否保留在可回收的 AssemblyLoadContext 中:False
//CLR 版本的文件夹名:v4.0.30319
//当前程序集是否在当前进程中动态生成的:False
//当前程序集是否以完全信任方式加载:True
//当前程序集清单的模块:ConsoleApp3.dll
//获取包含此程序集中模块的集合:System.Reflection.RuntimeModule[]
//程序集被加载到只反射上下文而不是执行上下文中:False
//CLR 对此程序集强制执行的安全规则集:None
//程序集下包含的类型:
//类:Program
//类:Person
//类:Employee
Assembly方法的应用
使用System.Reflection.Assembly类动态加载程序集(.dll)
Assembly类可以获得程序集的信息,也可以动态的加载程序集,以及在程序集中查找类型信息,并创建该类型的实例。 使用Assembly类可以降低程序集之间的耦合,有利于软件结构的合理化。
Assembly.Load()方法,Assembly.LoadFrom()方法,Assembly.LoadFile()方法的区别!
LoadFrom()、LoadFile()这俩方法会锁住文件,导致程序运行期间无法对load过的程序集文件进行更名/删除/覆盖等等操作,考虑用Assembly.Load()文件字节组替代:Load()其他方法加载文件也会锁住文件。
以下程序集不能共享 JIT 编译代码:使用Assembly 类的 LoadFrom 方法加载到“加载源”上下文中的程序集,或者使用 Load 方法的重载(指定字节数组 Load(byte[] rawAssembly、Load(byte[] rawAssembly, byte[]? rawSymbolStore))从图像加载的程序集。也就是说用这些方法加载的程序集只能给当期程序集使用,不能共享给其他程序集使用 详细请看:应用程序域和程序集
(1)Assembly.Load() 加载程序集
在使用这个函数之前要添加对程序集的引用,以.net core 5.0为例。
点击确定。添加成功后,查看项目的配置文件ConsoleApp4.csproj
此时会多出一条配置信息 如下图所示,很多时候load()无法加载函数都是因为配置文件未添加引用程序集信息。也可以手动添加该信息 引用程序集。
以上配置完成后就可以在.net core中正常使用Load函数加载程序集了。.net framework框架下也要添加程序集的引用
// Assembly.Load 函数的使用
Byte[] syd = System.IO.File.ReadAllBytes("Education.dll");//在指定的路径下获取程序集,不需要添加引用,默认当前当前程序集的目录下获取
Assembly assemblyLoadByte = Assembly.Load(syd); //必须把程序集添加为引用 才能正常使用该函数功能
Assembly assemblyLoadFullname= Assembly.Load("Education, Version = 1.1.0.0, Culture = neutral, PublicKeyToken = be45ec9bf8b890a7");
Assembly assemblyLoadPartialname = Assembly.Load("Education");
(2)Assembly.LoadFrom()加载 Assembly对象
LoadFrom()方法可以从指定文件中加载程序集,通过查找程序集的AssemblyRef元数据表,得知所有引用和需要的程序集,然后在内部调用Load()方法进行加载。
加载进的程序集实例存储在 AssemblyLoadContext.Default这个context中,和程序的依赖项存储在一起。如果希望存储在单独的context中 ,查看AssemblyLoadContext详细用法
例如:
Assembly.LoadFrom(@"C:\ABC\Test.dll");
Assembly ass = Assembly.LoadFrom("ClassLibrary831.dll");//文件在当前程序目录下
这个方法从指定的路径来加载程序集,实际上这个方法被调用的时候,CLR会打开这个文件,获取其中的程序集版本,语言文化,公钥标记等信息,把他们传递给 Load方法,接着,Load方法采用上面的策略来查找程序集。如果找到了程序集,会和LoadFrom方法中指定的路径做比较,如果路径相同,该程序集会被认为是应用程序的一部分,如果路径不同或Load方法没有找到程序集,那该程序集只是被作为一个“数据文件”来加载,不会被认为是应用程序的一部分。 这就是在第1点中提到的Load方法比LoadFrom方法的执行效率高的原因。另外,由于可能把程序集作为“数据文件”来加载,所以使用 LoadFrom从不同路径加载相同程序集的时候会导致重复加载。当然这个方法会加载此程序集引用的其他程序集。
(3)Assembly.LoadFile()加载 Assembly对象
这个方法是从指定的文件来加载程序集,和上面方法的不同之处是这个方法不会加载此程序集引用的其他程序集!
结论:一般大家应该优先选择Load方法来加载程序集,如果遇到需要使用LoadFrom方法的时候,最好改变设计而用Load方法来代替!
(4) ,LoadWithParitalName方法
对于,LoadWithParitalName方法,推荐大家最好不要使用它,因为程序无法确定最终要去加载哪个程序集的版本,所以我们这里只是简单的介绍一下它的工作原理:你可以传递一个程序集标识给它,包括程序集名称,至于其他信息是可选的(区域信息,公有密钥等),该方法执行时,会首先检查应用程序中配置文件的qualifyAssembly节点,如果存在,则把该部分名称的程序集替换成完全的程序集标识,如果不存在,则使用程序集名称先到应用程序根目录下查找,然后是私有目录,没有找到的话,就到程序集全局缓存中查找。简单过程如下:
应用程序根目录 -> 应用程序私有目录 -> 程序集全局缓存.
Assembly.LoadFile 与 Assembly.LoadFrom的区别
1、Assembly.LoadFile只载入相应的dll文件,比如Assembly.LoadFile("abc.dll"),则载入abc.dll,假如abc.dll中引用了def.dll的话,def.dll并不会被载入。
Assembly.LoadFrom则不一样,它会载入dll文件及其引用的其他dll,比如上面的例子,def.dll也会被载入。
2、用Assembly.LoadFrom载入一个Assembly时,会先检查前面是否已经载入过相同名字的Assembly,比如abc.dll有两个版本(版本1在目录1下,版本2放在目录2下),程序一开始时载入了版本1,当使用Assembly.LoadFrom("2\\abc.dll")载入版本2时,不能载入,而是返回版本1。Assembly.LoadFile的话则不会做这样的检查,比如上面的例子换成Assembly.LoadFile的话,则能正确载入版本2。
LoadFile:加载指定路径上的程序集文件的内容。LoadFrom: 根据程序集的文件名加载程序集文件的内容。
Assembly.CreateInstance()创建实例
assembly.CreateInstance已经获知程序集所有元数据,所以只要指定命名空间.类名 就可以生成实例了。Activator.CreateInstance未获得元数据,所以需要typeof函数先获取元数据类型信息,然后才能实例化。点击查看Activator.CreateInstance实例化
// Assembly.Load 函数的使用
Byte[] syd = System.IO.File.ReadAllBytes("Education.dll");//在指定的路径下获取程序集,不需要添加引用,默认当前当前程序集的目录下获取
Assembly assemblyLoadByte = Assembly.Load(syd); //必须把程序集添加为引用 采用正常使用该函数功能
Assembly assemblyLoadFullname= Assembly.Load("Education, Version = 1.1.0.0, Culture = neutral, PublicKeyToken = be45ec9bf8b890a7");
Assembly assemblyLoadPartialname = Assembly.Load("Education"); //Assembly.CreateInstance根据空间名.类型名创建实例,已经获得程序集所有的元数据,所以可以用这种放射创建
object person = assemblyLoadByte.CreateInstance("People.Person");
object stu = assemblyLoadByte.CreateInstance("Education.Student");
Type studentType = assemblyLoadByte.GetType("Education.Student");//名空间+类名 才能挣钱获取类型
Assembly.GetExecutingAssembly();
Assembly assem = Assembly.GetExecutingAssembly(); //获取当前执行代码的程序集
Assembly其他应用
通过Assembly获取程序集中类
Type t = ass.GetType("ClassLibrary831.NewClass"); //参数必须是类的全名
通过Assembly获取程序集中所有的类
Type[] t = ass.GetTypes(); //通过程序集的名称反射
Assembly ass = Assembly.Load("ClassLibrary831");
Type t = ass.GetType("ClassLibrary831.NewClass");
object o = Activator.CreateInstance(t, "grayworm", "http://hi.baidu.com/grayworm");
MethodInfo mi = t.GetMethod("show");
mi.Invoke(o, null); //通过DLL文件全名反射其中的所有类型
Assembly assembly = Assembly.LoadFrom("xxx.dll的路径");
Type[] aa = a.GetTypes();
foreach(Type t in aa)
{
if(t.FullName == "a.b.c")
{
object o = Activator.CreateInstance(t);
}
}
【C#反射】Assembly的更多相关文章
- 关于反射Assembly.Load("程序集").CreateInstance("命名空间.类")
关于反射Assembly.Load("程序集").CreateInstance("命名空间.类") 而不管在哪一层写这段代码其中的("程序集" ...
- [转]C#反射-Assembly.Load、LoadFrom与LoadFile进阶
关于.NET中的反射,常用的有三个方法: Assembly.Load()Assembly.LoadFrom()Assembly.LoadFile() 下面说说这三个方法的区别和一些细节问题 1. As ...
- C#反射Assembly 详细说明
1.对C#反射机制的理解2.概念理解后,必须找到方法去完成,给出管理的主要语法3.最终给出实用的例子,反射出来dll中的方法 反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等 ...
- C#中的反射 Assembly.Load() Assembly.LoadFrom()
一些关于C#反射的知识,估计也就最多达到使用API的程度,至于要深入了解,以现在的水平估计很难做到,所以下面此篇文章,以作为一个阶段的总结. 对于反射的总结,我想从以下几个方面展开,首先是反射程序集, ...
- C#反射Assembly 具体说明
1.对C#反射机制的理解 2.概念理解后,必须找到方法去完毕,给出管理的主要语法 3.终于给出有用的样例,反射出来dll中的方法 反射是一个程序集发现及执行的过程,通过反射能够得到*.exe或*.dl ...
- C#反射-Assembly.Load、LoadFrom与LoadFile
反射Demo: public class Person { public int Age; public void SayHello() { Console.WriteLine("Hello ...
- C#反射Assembly 详细说明,有项目例子
1.对C#反射机制的理解2.概念理解后,必须找到方法去完成,给出管理的主要语法3.最终给出实用的例子,反射出来dll中的方法 反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等 ...
- C#反射Assembly 详细说明(转)
1.对C#反射机制的理解2.概念理解后,必须找到方法去完成,给出管理的主要语法3.最终给出实用的例子,反射出来dll中的方法 反射是一个程序集发现及运行的过程,通过反射可以得到*.exe或*.dll等 ...
- c#利用反射Assembly 对类和成员属性进行操作
protected static void test() { //获取程序集 Assembly assembly = System.Reflection.Assembly.GetExecutingAs ...
随机推荐
- [Vue] Vue2 + @vue/composition-api 的一个坑
Vue2 + @vue/composition-api 和 Vue3 composition api 不一致的地方(待验证) <div v-for="item in arr" ...
- 【机器学习基础】无监督学习(1)——PCA
前面对半监督学习部分作了简单的介绍,这里开始了解有关无监督学习的部分,无监督学习内容稍微较多,本节主要介绍无监督学习中的PCA降维的基本原理和实现. PCA 0.无监督学习简介 相较于有监督学习和半监 ...
- MyCms 开源自媒体系统后台 角色管理&管理员管理操作说明
角色管理 功能说明 一.添加角色基本信息 填写角色名称.简要描述(一般以角色功能.职位等信息来命名) 二.角色授权 点击右侧的"授权"按钮,进行对角色授权,选择需要授权的功能模块后 ...
- gin框架中的中间件
全局中间件 所有请求都经过此中间件 中间件中设置值 func MiddleWare() gin.HandlerFunc { return func(context *gin.Context) { t ...
- 什么是HTTP? HTTP 和 HTTPS 的区别?
转载地址: 面试官:什么是HTTP? HTTP 和 HTTPS 的区别? 一.HTTP HTTP (HyperText Transfer Protocol),即超文本运输协议,是实现网络通信的一种规范 ...
- javaweb登陆界面实现不同角色进入不同界面
目录结构 类包: AccountBean.java AccountDao.java JudgeServlet.java 登陆界面: index.jsp 代码实现 AccountBean.java pa ...
- Python初学笔记之可变类型、不可变类型
python中 可变类型: 列表 list 字典 dict 不可变类型: 数字型:int.float.complex.bool.long 字符型 str 元组 tuple id(i):通过id查看变量 ...
- Linux添加用户组和添加用户
1.用户组 添加组:groupadd 组名 [root@Server-n93yom ~]# groupadd dev [root@Server-n93yom ~]# cat /etc/group | ...
- Android下数据库操作——增删改查
Android下数据库第一种方式增删改查 1.创建一个帮助类的对象,调用getReadableDatabase方法,返回一个SqliteDatebase对象 2.使用SqliteDat ...
- PHP中的一些常用函数收集
<?php //===============================时间日期=============================== //y返回年最后两位,Y年四位数,m月份数字 ...