C# Assembly 程序集

摘要


在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()
image.png

将编译好的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运行时会尝试解析并加载程序集的依赖项,并且相同的程序集不会被重复加载到相同的上下文中。
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容