Rumah pembangunan bahagian belakang Tutorial C#.Net C#程序集和反射的图文代码详解

C#程序集和反射的图文代码详解

Mar 29, 2017 am 11:45 AM
c# refleksi

本文主要介绍了C# 程序集和反射的相关知识。具有一定的参考价值,下面跟着小编一起来看下吧

这里我又唠叨几句,大家在学习的时候,如看书或者看视频时觉得非常爽,因为感觉基本都看得懂也都挺容易的,其实看懂是一回事,你自己会动手做出来是一回事,自己能够说出来又是另一回事了。应该把学到的东西变成自己的东西,而不是依样画瓢。

在说反射之前,我们先来了解一下什么是程序集?

程序集

程序集是.net中的概念,程序集可以看作是给一堆相关类打一个包,相当于java中的jar包。

程序集包含:

  • 资源文件

  • 类型元数据(描述在代码中定义的每一类型和成员,二进制形式)

  • IL代码(这些都被封装在exe或dll中)

exe与dll的区别。

exe可以运行,dll不能直接运行,因为exe中有一个main函数(入口函数)。

类型元数据这些信息可以通过AssemblyInfo.cs文件来自定义。在每一个.net项目中都存在一个AssemblyInfo.cs文件,代码格式:

using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
[assembly: AssemblyTitle("ReflectedDemo")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ReflectedDemo")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("7674d229-9929-4ec8-b543-4d05c6500863")]
// 程序集的版本信息由下面四个值组成: 
//
//   主版本
//   次版本 
//   生成号
//   修订号
//
// 可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
// 方法是按如下所示使用“*”: 
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
Salin selepas log masuk

这些信息在哪里体现呢?就在我们程序集的属性当中进行体现

我们平时在安装一些CS客户端程序的时候,在安装目录下面会看见许多的程序集文件。

使用程序集的好处

  • 程序中只引用必须的程序集,减小程序的尺寸。

  • 程序集可以封装一些代码,只提供必要的访问接口。

  • 方便扩展。

如何添加程序集的引用?

直接添加程序集路径或者添加解决方案中的项目引用。

当我们需要扩展一个程序的时候,你可能会直接在原有的项目中进行添加,那这样的话,如果你的这些代码想共享给别人使用呢?你就可以打包成一个程序集,然后别人只要通过引用你这个程序集就可以进行扩展了。像我们常见的.net第三方框架库,如log4net、unity等等。

注意:不能添加循环引用

什么是添加循环引用?就是说A项目如果添加了B项目的项目引用,那么此时B项目不能再添加A项目的项目引用,也就是说添加项目引用时,必须是单向的,像我们常见的三层框架之间的项目引用。

反射

关于反射,你只要是做.net开发,你就一定天天在用。因为VS的智能提示就是通过应用了反射技术来实现的,还有我们常用的反编译神器Reflector.exe,看它的名字就知道了。项目中比较常见的,是通过结合配置文件来动态实例化对象,如切换数据库实例,或者Sprint.net的通过配置文件来实现依赖注入等。

反射技术其实就是动态获取程序集的元数据的功能,反射通过动态加载dll,然后对其进行解析,从而创建对象,调用成员。

Type是对类的描述,Type类是实现反射的一个重要的类,通过它我们可以获取类中的所有信息,包括方法、属性等。可以动态调用类的属性、方法。

反射的出现让创建对象的方式发生了改变,因为过去面完创建对象都是直接通过new。

dll里面有两部分东西:IL中间语言和metadate元素据。

在.NET中反射用到命名空间是System.Reflection,这里我先通过一个Demo来看反射能做些什么

1、 新建控制台项目ReflectedDemo

2、 新建类库项目My.Sqlserver.Dal

新建两个类SqlServerHelper和SqlCmd,前者为共有类,后者为私有类

namespace My.Sqlserver.Dal
{
  public class SqlServerHelper
  {
    private int age = 16;
    public string Name { get; set; }
    public string Query()
    {
      return string.Empty;
    }
  }
  class SqlCmd
  {
  }
}
Salin selepas log masuk

3、 项目ReflectedDemo,添加My.Sqlserver.Dal的项目引用,我这样做的目的是为了方便项目ReflectedDemo中的bin目录中时刻存在My.Sqlserver.Dal.dll程序集。

using System;
using System.Reflection;
namespace ReflectedDemo
{
  class Program
  {
    static void Main(string[] args)
    {
      //加载程序集文件,在bin目录中查找
      Assembly assembly = Assembly.Load("My.Sqlserver.Dal");
      Console.WriteLine("----------------Modules----------------------");
      var modules = assembly.GetModules();
      foreach(var module in modules)
      {
        Console.WriteLine(module.Name);
      }
      Console.WriteLine("----------------Types----------------------");
      var types = assembly.GetTypes(); //获取程序集中所有的类型,包括公开的和不公开的
      foreach(var type in types)
      {
        Console.WriteLine(type.Name);
        Console.WriteLine(type.FullName);
        var members= type.GetMembers(); //获取Type中所有的公共成员
        Console.WriteLine("----------------members----------------------");
        foreach(var m in members)
        {
          Console.WriteLine(m.Name);
        }
      }
      Console.WriteLine("----------------GetExportedTypes----------------------");
      var exportedTypes = assembly.GetExportedTypes(); //获取程序集中所有的公共类型
      foreach(var t in exportedTypes)
      {
        Console.WriteLine(t.Name);
      }
      Console.WriteLine("----------------GetType----------------------");
      var typeName= assembly.GetType("SqlServerHelper");//获取程序集中指定名称的类型对象
      Console.WriteLine(typeName.Name);
    }
  }
}
Salin selepas log masuk

动态创建对象

通过ass.CreateInstance(string typeName) 和Activator.CreateInstance(Type t)方法

他们之间的区别

ass.CreateInstance(string typeName) 会动态调用类的无参构造函数创建一个对象,返回值就是创建的对象,如果没有无参构造函数就会报错。


Assembly assembly = Assembly.Load("My.Sqlserver.Dal");
object obj = assembly.CreateInstance("My.Sqlserver.Dal.SqlServerHelper");
Console.WriteLine(obj.GetType().ToString());
Salin selepas log masuk

如果我们来修改SqlServerHelper类的代码,添加如下构造函数:

    public SqlServerHelper(int age)
    {
      this.age = age;
    }
Salin selepas log masuk

这个时候再来运行创建实例的代码就会报错了,而编译时是不报错的。

所以我们一般推荐使用Activator.CreateInstance方法来创建反射对象,因为此方法有许多重载,支持将参数传递给构造函数。

此时再调用就不会出现异常了。

Type类中有三个用得比较多的方法:

  • bool IsAssignableFrom(Type t):是否可以从t赋值,判断当前的类型变量是不是可以接受t类型变量的赋值。

  • bool IsInstanceOfType(object o):判断对象o是否是当前类的实例,当前类可以是o的类、父类、接口

  • bool IsSubclassOf(Type t):判断当前类是否是t的子类

Type类中还有一个IsAbstract属性:判断是否为抽象的,包含接口。

它们常用的原因是我们通过反射可以取到的东西太多了,我们需要对数据进行过滤。

添加类BaseSql,让类SqlServerHelper继承自BaseSql

然后查看调用代码:

      bool result = typeof(BaseSql).IsAssignableFrom(typeof(SqlServerHelper));
      Console.WriteLine(result);
Salin selepas log masuk


   SqlServerHelper _SqlServerHelper = new SqlServerHelper(1);
   bool result = typeof(SqlServerHelper).IsInstanceOfType(_SqlServerHelper);
   Console.WriteLine(result);
Salin selepas log masuk


      SqlServerHelper _SqlServerHelper = new SqlServerHelper(1);
      bool result = typeof(SqlServerHelper).IsSubclassOf(typeof(BaseSql));
      Console.WriteLine(result);
Salin selepas log masuk

项目中常用的利用反射来动态切换数据库Demo:

新建类库项目My.Sql.IDal,并添加接口ISqlHelper。通过接口来实现数据库操作的类的解耦,因为接口是抽象的。

  public interface ISqlHelper
  {
    string Query();
  }
Salin selepas log masuk

添加类库项目My.MySql.Dal,并新增类MySqlHelper.cs

My.Sqlserver.Dal、My.MySql.Dal项目分别添加对项目My.Sql.IDal的引用。让SqlServerHelper继承自接口ISqlHelper

public class MySqlHelper : ISqlHelper
  {
    public string Query()
    {
       return this.GetType().ToString();
    }
  }
  public class SqlServerHelper :ISqlHelper
  {
    private int age = 16;
    public string Name { get; set; }
    public string Query()
    {
      return this.GetType().ToString();
    }
  }
Salin selepas log masuk

添加App.config配置项

 <appSettings>
  <add key="DBName" value="My.Sqlserver.Dal,SqlServerHelper"/>
 </appSettings>
Salin selepas log masuk

ReflectedDemo项目中Program.cs调用代码:

string str = ConfigurationManager.AppSettings["DBName"];
      string strAssembly = str.Split(&#39;,&#39;)[0];
      string strClass=str.Split(&#39;,&#39;)[1];
      Assembly assembly = Assembly.Load(strAssembly);
      Type t = assembly.GetType(strAssembly + "." + strClass);
      ISqlHelper obj = Activator.CreateInstance(t) as ISqlHelper;
      Console.WriteLine(obj.Query());
Salin selepas log masuk

这样每次需要切换数据库时,只要修改配置文件就可以了。

项目结构:

注意:反射虽然很强大,但却是比较耗性能的,所以一般和缓存结合起来使用。

Atas ialah kandungan terperinci C#程序集和反射的图文代码详解. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

<🎜>: Bubble Gum Simulator Infinity - Cara Mendapatkan dan Menggunakan Kekunci Diraja
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Nordhold: Sistem Fusion, dijelaskan
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌
Mandragora: Whispers of the Witch Tree - Cara Membuka Kunci Cangkuk Bergelut
3 minggu yang lalu By 尊渡假赌尊渡假赌尊渡假赌

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas

Tutorial Java
1667
14
Tutorial PHP
1273
29
Tutorial C#
1255
24
Direktori Aktif dengan C# Direktori Aktif dengan C# Sep 03, 2024 pm 03:33 PM

Panduan untuk Active Directory dengan C#. Di sini kita membincangkan pengenalan dan cara Active Directory berfungsi dalam C# bersama-sama dengan sintaks dan contoh.

Penjana Nombor Rawak dalam C# Penjana Nombor Rawak dalam C# Sep 03, 2024 pm 03:34 PM

Panduan untuk Penjana Nombor Rawak dalam C#. Di sini kita membincangkan cara Penjana Nombor Rawak berfungsi, konsep nombor pseudo-rawak dan selamat.

Paparan Grid Data C# Paparan Grid Data C# Sep 03, 2024 pm 03:32 PM

Panduan untuk Paparan Grid Data C#. Di sini kita membincangkan contoh cara paparan grid data boleh dimuatkan dan dieksport daripada pangkalan data SQL atau fail excel.

Faktorial dalam C# Faktorial dalam C# Sep 03, 2024 pm 03:34 PM

Panduan untuk Faktorial dalam C#. Di sini kita membincangkan pengenalan kepada faktorial dalam c# bersama-sama dengan contoh dan pelaksanaan kod yang berbeza.

Perbezaan antara multithreading dan asynchronous C# Perbezaan antara multithreading dan asynchronous C# Apr 03, 2025 pm 02:57 PM

Perbezaan antara multithreading dan asynchronous adalah bahawa multithreading melaksanakan pelbagai benang pada masa yang sama, sementara secara tidak sengaja melakukan operasi tanpa menyekat benang semasa. Multithreading digunakan untuk tugas-tugas yang berintensifkan, sementara asynchronously digunakan untuk interaksi pengguna. Kelebihan multi-threading adalah untuk meningkatkan prestasi pengkomputeran, sementara kelebihan asynchronous adalah untuk tidak menghalang benang UI. Memilih multithreading atau asynchronous bergantung kepada sifat tugas: tugas-tugas intensif pengiraan menggunakan multithreading, tugas yang berinteraksi dengan sumber luaran dan perlu menyimpan respons UI menggunakan asynchronous.

Corak dalam C# Corak dalam C# Sep 03, 2024 pm 03:33 PM

Panduan kepada Corak dalam C#. Di sini kita membincangkan pengenalan dan 3 jenis Corak teratas dalam C# bersama-sama dengan contoh dan pelaksanaan kodnya.

Nombor Perdana dalam C# Nombor Perdana dalam C# Sep 03, 2024 pm 03:35 PM

Panduan Nombor Perdana dalam C#. Di sini kita membincangkan pengenalan dan contoh nombor perdana dalam c# bersama dengan pelaksanaan kod.

Cara menukar format XML Cara menukar format XML Apr 03, 2025 am 08:42 AM

Terdapat beberapa cara untuk mengubah format XML: mengedit secara manual dengan editor teks seperti Notepad; Memformat secara automatik dengan alat pemformatan XML dalam talian atau desktop seperti XMLBeAutifier; Tentukan peraturan penukaran menggunakan alat penukaran XML seperti XSLT; atau menghuraikan dan beroperasi menggunakan bahasa pengaturcaraan seperti Python. Berhati -hati apabila mengubahsuai dan membuat sandaran fail asal.

See all articles