C# 反射

参考以下文章:
http://www.cnblogs.com/binfire/archive/2013/01/17/2864887.html C# 反射机制
https://blog.csdn.net/sibaison/article/details/70168338 C#装配件
https://bbs.csdn.net/topics/60376191 程序集与装配件是不是同一个概念
https://www.cnblogs.com/CHNMurphy/p/8607752.html C# 中使用反射的优缺点
https://www.cnblogs.com/weloveshare/p/5754553.html c# 早绑定晚绑定
https://bbs.csdn.net/topics/391968018 为什么反射效率那么低?

编译程序集或者模块时,编译器会创建一个类定义表,一个字段定义表,和一个方法定义表等。元数据是编译以后的最基本数据单元,就是一大堆的表。

反射:审查元数据并收集关于它的类型信息的能力。这是.Net中获取运行时类型信息的方式,.Net的应用程序由几个部分:‘程序集(Assembly)’、‘模块(Module)’、‘类型(class)’组成,而反射提供一种编程的方式,让程序员可以在程序运行期获得这几个组成部分的相关信息,

System.reflection命名空间包含的几个类,允许你通过反射获得这些元数据表的信息。
System.Reflection.Assembly类可以获得正在运行的装配件信息,也可以动态的加载装配件,以及在装配件中查找类型信息,并创建该类型的实例。(编译好的程序是由多个装配件组成,每个装配件里都包含了元数据,元数据中就存储了自描述信息,如接口、类型、方法等细节,分别描述每个装配件的内容,并可以判断装配件是否装满,还可调用其它装配件的信息。.NET运行时就会加载这个程序装配件,并利用装配件的自描述功能来验证装配件程序的合法性,合法才运行。)
System.Type类可以获得对象的类型信息,包括:方法、构造器、属性等。
System.Reflection.MethodInfo包含方法的信息,包括:方法的名称、参数、返回值等。

反射的优点:
反射提高了程序的灵活性和扩展性,降低耦合性,提高自适应能力。它允许程序创建和控制任何类的对象,无需提前硬编码目标类。
反射的缺点:
性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因为反射是要动态的获取实例调用方法,这就要消耗资源去查找和计算。反射的过程中有递归和遍历的操作,这些都需要时间。     
模糊程序的内部逻辑:反射代码比相应的直接代码更复杂,因而会带来维护问题。程序员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术。

早绑定 early binding:这种方式运行效率高.
在编译的时候就已经却确定了将来程序运行基类或者派生类的哪个方法。
在编译代码的时候根据引用类型就决定了运行该引用类型中定义的方法。即基类方法。

晚绑定 late binding:
只有在运行的时候才能决定运行基类或者派生类中的方法,C#中用new和override实现了晚绑定。
运行的时候将根据该实际类型,而不是引用类型来调用相应的方法,即取决于我们new了什么对象。

动态绑定 dynamic binding
dynamic声明变量的好处是,编译器在编译时并不知道它引用对象的确切类型,而要到运行时才知道。因此,我们可以通过动态绑定在运行时来操作一些类型的属性、方法等。

DLR(动态语言运行时)使得C#中可以调用动态语言以及使用dynamic的动态类型。它允许添加动态语言,如ruby python。

为什么使用反射?
通俗的说,反射可以使用未知的dll。
你直接引用DLL,那是静态的,一旦改变DLL,就必须重新编译,生产新的软件,但是动态引用DLL就不需要。
反射可以用来开发程序插件一类的,别人开发的插件只要继承某个已知的接口,就可以利用反射动态加载进来,然后实例化接口调用,就可以载入别人的插件了。猜想,不开源的插件使用,那为什么不直接使用命名空间呢?
你提供接口别人提供这个接口的实现,但是不给你源码不给你方法说明,那么这个时候你就只有用反射调用它的实现,以接口形式来使用了。常见的IOC就是这样组织人民这样干的东西。
就举一个例子吧,如果程序中某个地方需要实例化整个程序中所以继承某接口的类,这个时候难道你要去程序中找到所有符合条件的类再实例化?而反射就可以很好的解决这个问题。
dll各种版本的变化,你不可能每次都编译成同一个版本,这样管理会混乱。
这样子也是一种很好的我解藕方式,你如果dll很庞大,引用进工程是不会很方便的。

https://bbs.csdn.net/wap/topics/390584105 C# 为什么要用反射,什么情况必须使用反射。
https://bbs.csdn.net/topics/390149930 C#中使用反射的意义?为什么要使用反射

具体操作如下:

http://www.cnblogs.com/dw039/p/7476011.html C# 反射、与dynamic最佳组合
https://blog.csdn.net/lianjiangwei/article/details/47207875【C#】:浅谈反射机制
 

1,拿到需要的类型,创建对象,操作变量,调用函数。
2,如何拿到需要的类型?如果需要的类型是内部的,是确定的,那就不需要加载程序集,直接使用就行,如果是外部的,或者是不确定的,则需要加载相应的程序集。
3,无论如何,我们需要的不过就是能创建对象,调用函数,操作变量。

//加载DLL,如果是内部的,就不需要加载dll
Assembly ass = Assembly.LoadFrom(AppDomain.CurrentDomain.BaseDirectory+"bin\\WebApplication1.dll");
//获得类型,如果是确定的,直接使用该类型就好,如果是不确定,一般通过string参数来传递该类型
Type t = ass.GetType("WebApplication1.MainPage");
//创建实例对象,使用var会更加方便
object o = Activator.CreateInstance(t);
//操作变量
t.GetProperty("Age").SetValue(instance, 18, null);
//调用方法
MethodInfo mi = t.GetMethod("RunJs1");   mi.Invoke(o, null});
//使用dynamic动态类型,直接拿到对象,调用方法
dynamic dy = Activator.CreateInstance(t); dy.RunJs1();

使用反射实现工厂模式如下:

using System.Reflection;

public class ReceiveTest : MonoBehaviour
{
    public void CallFun(string name)
    {
        dynamic tmp = Activator.CreateInstance(Type.GetType(name));//根据name来决定使用哪个对象实例
        tmp.Fun();
    }
}

public interface IFruitTest
{
    void Fun();
}

public class AppleTest : IFruitTest
{
    public void Fun()
    {
        Debug.Log("AppleTest Fun");
    }
}

public class OrangeTest : IFruitTest
{
    public void Fun()
    {
        Debug.Log("OrangeTest Fun");
    }
}

 

 

 

 

 

 

 

 

在使用Python来安装geopandas包时,由于geopandas依赖于几个其他的Python库(如GDAL, Fiona, Pyproj, Shapely等),因此安装过程可能需要一些额外的步骤。以下是一个基本的安装指南,适用于大多数用户: 使用pip安装 确保Python和pip已安装: 首先,确保你的计算机上已安装了Python和pip。pip是Python的包管理工具,用于安装和管理Python包。 安装依赖库: 由于geopandas依赖于GDAL, Fiona, Pyproj, Shapely等库,你可能需要先安装这些库。通常,你可以通过pip直接安装这些库,但有时候可能需要从其他源下载预编译的二进制包(wheel文件),特别是GDAL和Fiona,因为它们可能包含一些系统级的依赖。 bash pip install GDAL Fiona Pyproj Shapely 注意:在某些系统上,直接使用pip安装GDAL和Fiona可能会遇到问题,因为它们需要编译一些C/C++代码。如果遇到问题,你可以考虑使用conda(一个Python包、依赖和环境管理器)来安装这些库,或者从Unofficial Windows Binaries for Python Extension Packages这样的网站下载预编译的wheel文件。 安装geopandas: 在安装了所有依赖库之后,你可以使用pip来安装geopandas。 bash pip install geopandas 使用conda安装 如果你正在使用conda作为你的Python包管理器,那么安装geopandas和它的依赖可能会更简单一些。 创建一个新的conda环境(可选,但推荐): bash conda create -n geoenv python=3.x anaconda conda activate geoenv 其中3.x是你希望使用的Python版本。 安装geopandas: 使用conda-forge频道来安装geopandas,因为它提供了许多地理空间相关的包。 bash conda install -c conda-forge geopandas 这条命令会自动安装geopandas及其所有依赖。 注意事项 如果你在安装过程中遇到任何问题,比如编译错误或依赖问题,请检查你的Python版本和pip/conda的版本是否是最新的,或者尝试在不同的环境中安装。 某些库(如GDAL)可能需要额外的系统级依赖,如地理空间库(如PROJ和GEOS)。这些依赖可能需要单独安装,具体取决于你的操作系统。 如果你在Windows上遇到问题,并且pip安装失败,尝试从Unofficial Windows Binaries for Python Extension Packages网站下载相应的wheel文件,并使用pip进行安装。 脚本示例 虽然你的问题主要是关于如何安装geopandas,但如果你想要一个Python脚本来重命名文件夹下的文件,在原始名字前面加上字符串"geopandas",以下是一个简单的示例: python import os # 指定文件夹路径 folder_path = 'path/to/your/folder' # 遍历文件夹中的文件 for filename in os.listdir(folder_path): # 构造原始文件路径 old_file_path = os.path.join(folder_path, filename) # 构造新文件名 new_filename = 'geopandas_' + filename # 构造新文件路径 new_file_path = os.path.join(folder_path, new_filename) # 重命名文件 os.rename(old_file_path, new_file_path) print(f'Renamed "{filename}" to "{new_filename}"') 请确保将'path/to/your/folder'替换为你想要重命名文件的实际文件夹路径。
C# 反射是指在运行时动态地获取类的信息,通过反射可以获取类的属性、方法、事件等信息,以及动态创建对象、调用方法、获取值等操作。这使得我们能够在运行时动态地编写代码,可以写出更加灵活和可扩展的程序。 C# 反射的核心是 `System.Reflection` 命名空间,该命名空间包含了许多与反射相关的类和接口,比如 `Type` 类、`MethodInfo` 类、`PropertyInfo` 类等。 下面是一些常用的反射操作: 1. 获取类型信息 可以使用 `typeof` 关键字或者 `Type.GetType()` 方法来获取类型的信息。`typeof` 关键字用于获取编译时已知的类型信息,而 `Type.GetType()` 方法则可以通过类型名称获取运行时的类型信息。 ```csharp // 获取 System.String 类型的信息 Type type1 = typeof(System.String); // 获取指定类型名称的信息 Type type2 = Type.GetType("System.String"); ``` 2. 获取成员信息 可以使用 `Type.GetMembers()` 方法获取类型的所有成员信息,包括属性、方法、字段、事件等。也可以使用 `Type.GetMethod()`、`Type.GetProperty()`、`Type.GetField()`、`Type.GetEvent()` 等方法获取指定成员的信息。 ```csharp Type type = typeof(Person); // 获取类型的所有成员信息 MemberInfo[] members = type.GetMembers(); // 获取指定属性的信息 PropertyInfo property = type.GetProperty("Name"); // 获取指定方法的信息 MethodInfo method = type.GetMethod("SayHello"); // 获取指定字段的信息 FieldInfo field = type.GetField("Age"); // 获取指定事件的信息 EventInfo eventInfo = type.GetEvent("PropertyChanged"); ``` 3. 动态创建对象 可以使用 `Activator.CreateInstance()` 方法动态创建对象,也可以使用 `Type.InvokeMember()` 方法调用构造函数来创建对象。 ```csharp Type type = typeof(Person); // 使用 Activator.CreateInstance() 方法创建对象 Person person1 = (Person)Activator.CreateInstance(type); // 使用 Type.InvokeMember() 方法调用构造函数创建对象 Person person2 = (Person)type.InvokeMember(null, BindingFlags.CreateInstance, null, null, new object[] { "Tom", 18 }); ``` 4. 调用成员 可以使用 `MethodInfo.Invoke()` 方法调用方法,也可以使用 `PropertyInfo.SetValue()` 方法设置属性的值,使用 `FieldInfo.SetValue()` 方法设置字段的值。 ```csharp Type type = typeof(Person); Person person = new Person("Tom", 18); // 调用方法 MethodInfo method = type.GetMethod("SayHello"); method.Invoke(person, null); // 设置属性的值 PropertyInfo property = type.GetProperty("Name"); property.SetValue(person, "Jerry", null); // 设置字段的值 FieldInfo field = type.GetField("Age"); field.SetValue(person, 20); ``` 以上是 C# 反射的一些基本操作,反射的应用非常广泛,可以用来实现插件式开发、ORM 映射等功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值