摘要
在C#中,程序集的结构非常灵活,它们可以包含不同类型的文件,例如可执行文件、元数据文件、配置文件等等。不同类型的文件可以通过引用的方式相互关联。程序集也可以是单例的,也就是说,它只包含一个实例。在这种情况下,它是不可修改的,这是因为任何对程序集的修改都会影响到整个应用程序的行为。
在程序集中,文件是一个基本的组成部分,每个文件都是一个字节序列。在生成程序集时,每个文件都会被编译成字节码,这些字节码是一种可以在虚拟机中运行的中间代码。这样,每个文件就可以被当作一个程序集来看待,而不是作为一个单独的文件来处理。
程序集的名称是程序集文件的唯一标识符。每个程序集都有一个标识符,它是程序集文件的文件名。在应用程序中,程序集名称是由程序集生成器生成的。在编译时,程序集生成器会检查程序集名称是否已经存在,如果存在,则会引发错误。因此,程序集名称必须是唯一的。
在程序集中,文件可以是可执行文件、元数据文件、配置文件等等。这些文件的结构可以有所不同,但它们都有一个共同的特点:它们都是由C#编译器编译生成的。在编译时,编译器会将代码转换为字节码,然后将字节码保存到程序集文件中。这些文件的编译结果都是字节码,它们可以在虚拟机中运行。
程序集是C#中非常重要的概念,它是代码进行编译后生成的一个逻辑单元,把相关的代码和类型进行组合,然后生成PE文件。程序集的结构由许多不同的元素组成,其中最基本的元素是文件。不同类型的文件可以通过引用的方式相互关联。程序集也可以是单例的,也就是说,它只包含一个实例。在编译时,编译器会将代码转换为字节码,然后将字节码保存到程序集文件中。这些文件的编译结果都是字节码,它们可以在虚拟机中运行。
正文
常见的两种程序集:
可执行文件(.exe文件)和 类库文件(.dll文件)。
在VS开发环境中,一个解决方案可以包含多个项目,而每个项目就是一个程序集。
查询继承父类的程序集合BaseType
.NET的程序集对象Assembly有个属性BaseType,来返回当前程序集的基础类型,默认是Object。通过该属性可以判断某个程序集是否是继承了某个父类;
程序集B被A程序引用,获取A程序集的信息GetCallingAssembly
.NET的程序集对象Assembly有个方法GetCallingAssembly获取当前程序集被调用的上级程序集的信息;
查找当前项目的程序集GetAssemblies
查找当前项目所有程序集的方法System.AppDomain.CurrentDomain.GetAssemblies();
使用Assembly
using System.Reflection;
实例化
我们创建一个项目Is.User
创建一个类 Class Library
namespace Is.User
{
public class User
{
public string Id { get; set; }
public string Name { get; set; }
public string Show()
{
return this.Id + " " + this.Name;
}
}
}
这里我们不去在主项目中引用它,准备通过Assembly 中的方法动态实例化
常用的有三个方法:
- Assembly.Load()
- Assembly.LoadFrom()
- Assembly.LoadFile()

将编译好的Is.User.dll 拷贝到对应目录。
private void btnInstance_Click(object sender, EventArgs e)
{
Assembly assembly = Assembly.LoadFrom("./Is.User.dll"); //通过文件路径加载
Type[] allTypes = assembly.GetTypes();
Type type = assembly.GetType("Is.User.User");
object user = Activator.CreateInstance(type);
type.GetProperty("Id").SetValue(user, "1");
type.GetProperty("Name").SetValue(user, "张飞");
var ret= type.GetMethod("Show").Invoke(user, new object[] { });
MessageBox.Show(ret.ToString());
}
修改成LoadFile效果一样
Assembly assembly = Assembly.LoadFile("./Is.User.dll");
LoadFile与LoadFrom的区别
Assembly.LoadFile
-
路径:
LoadFile方法直接通过完整路径加载程序集文件。它不使用加载上下文,并且不解析程序集的依赖项。 -
上下文:使用
LoadFile加载的程序集不会被放入任何上下文中。这意味着即使相同的程序集被多次加载,每次加载都会被视为不同的程序集。 -
使用场景:当你需要直接从指定路径加载程序集,而不关心其依赖关系,或者需要独立于应用程序默认上下文加载程序集时,可以使用
LoadFile。
Assembly.LoadFrom
-
路径:
LoadFrom也允许通过路径加载程序集,但它会尝试解析程序集的依赖项,并使用加载上下文。 -
上下文:使用
LoadFrom加载的程序集被放入加载上下文中。这意味着如果相同的程序集(基于强名称和版本)已经存在于上下文中,它不会被重复加载。 -
使用场景:当你需要从特定路径加载程序集,并且希望.NET运行时自动解析并加载其依赖项时,
LoadFrom是一个更好的选择。这对于加载插件或扩展非常有用。
总结
- 使用
LoadFile时,程序集和其依赖项不会自动解析,每次加载都视为唯一,即使是相同的程序集。 - 使用
LoadFrom时,.NET运行时会尝试解析并加载程序集的依赖项,并且相同的程序集不会被重复加载到相同的上下文中。