当前位置: 首页 > 编程日记 > 正文

.net反射详解(转)

摘自:http://www.cnblogs.com/knowledgesea/archive/2013/03/02/2935920.html

概述反射

  • 通过反射可以提供类型信息,从而使得我们开发人员在运行时能够利用这些信息构造和使用对象。
  • 反射机制允许程序在执行过程中动态地添加各种功能。  

 运行时类型标识 

  • 运行时类型标识(RTTI),可以在程序执行期间判定对象类型。例如使用它能够确切地知道基类引用指向了什么类型对象。
  • 运行时类型标识,能预先测试某个强制类型转换操作,能否成功,从而避免无效的强制类型转换异常。
  • 在c#中有三个支持RTTI的关键字:is 、 as  、typeof。 下面依次介绍他们

is运算符:

通过is运算符,能够判断对象类型是否为特顶类型,如果两种类型是相同类型,或者两者之间存在引用,装箱拆箱转换,则表明两种类型是兼容的 

View Code
复制代码
class Program{static void Main(string[] args) { A a = new A(); B b = new B(); if (a is A) { Console.WriteLine("a is an A"); //这个打印,因为a 是 A 类型的对象  } if (b is A) { //这个打印,因为b是B类型的对象,而B类型派生于A类型,由于b对象可以转换为A类型,因此b对象与A类型是兼容的,但是反过来就不成立,例如下面不打印 Console.WriteLine("b is an A because it is derived from"); } if (a is B) { //这个不打印 Console.WriteLine("This won't display , because a not derived from B"); } if (a is object) { //这个打印 Console.WriteLine("a is an object"); } Console.ReadKey(); } } class A { } class B : A { }
复制代码

as运算符:

 在运行期间执行类型转换,并且能够使得类型转换失败不抛异常,而返回一个null值,其实as也可以看作一个is运算符的简化备选方式(看例子)。 

View Code
复制代码
 class Program{static void Main(string[] args) { A a = new A(); B b = new B(); if (a is B) { b = (B)a; //由于a变量不是B类型,因此这里将a变量转换为B类型是无效的。  } else { b = null; } if (b ==null) { //这个打印 Console.WriteLine("The cast in b=(B)a is not allowed"); } //上面使用as运算符,能够把两部合二为一。  b = a as B; //as类型先检查强制类型转换的有效性,如果有效,则执行强类型转换过程。这些都在这一句完成。 if (b == null) { //这个打印 Console.WriteLine("The cast in b=(B)a is not allowed"); } Console.ReadKey(); } } class A { } class B : A { }
复制代码

typeof运算符: 

 as ,is 能够测试两种类型的兼容性。但大多数情况下,还需要获得某个类型的具体信息。这就用到了typeof,它可以返回与具体类型相关的System.Type对象,通过System.Type对象可以去顶此类型的特征。一旦获得给定类型的Type对象,就可以通过使用该对象定义的各种属性,字段,方法来获取类型的具体信息。Type类包含了很多成员,在接下来的反射中再详细讨论。下面简单的演示Type对象,调用它的三个属性。

View Code
复制代码
  static void Main(string[] args){Type t=typeof(StringBuilder); Console.WriteLine(t.FullName); //FullName属性返回类型的全称 if (t.IsClass) { Console.WriteLine("is a class"); //打印  } if (t.IsSealed) //是否为密封类  { Console.WriteLine("is Sealed"); //打印  } Console.ReadKey(); }
复制代码

 反射的核心类:System.Type类

  • 许多支持反射的类都位于System.Reflection命名空间中,他们是.net  Reflection API的一部分,所以在使用的反射的程序中一般都要使用 System.Reflection的命名空间。
  • System. Type类包装了类型,因此是整个反射子系统的核心,这个类中包含了很多属性和方法,使用这些属性和方法可以在运行时得到类型的信息。
  • Type类派生于System.Reflection.MemberInfo抽象类

MemberInfo类中的只读属性

属性

描述

Type DeclaringType

获取声明该成员的类或接口的类型

MemberTypes  MemberType

获取成员的类型,这个值用于指示该成员是字段、方法、属性、事件、或构造函数

Int MetadataToken

获取与特定元数据相关的值

Module Module

获取一个代表反射类型所在模块(可执行文件)的Module对象

String  Name

成员的名称

Type  ReflectedType

反射的对象类型

请注意 

  • MemberType属性的返回类型为MemberTypes,这是一个枚举,它定义了用于表示不同成员的类型值。这些值包括:MemberTypes.Constructor,   MemberTypes.Method,      MemberTypes.Field,        MemberTypes.Event,      MemberTypes.Property。因此可以通过检查MemberType属性来确定成员的类型,例如,在MemberType属性的值为MemberTypes.Method时,该成员为方法
  • MemberInfo类还包含两个与特性相关的抽象方法:  
    1. GetCustomAttributes() :获得与主调对象关联的自定义特性列表。
    2. IsDefined(): 确定是否为主调对象定义了相应的特性。
    3. GetCustomAttributesData():返回有关自定义特性的信息(特性稍后便会提到)

当然除了MemberInfo类定义的方法和属性外,Type类自己也添加了许多属性和方法:如下表(只列出一些常用的,太多了,自己可以转定义Type类看下)

Type类定义的方法

方法

功能

ConstructorInfo[]  GetConstructors()

获取指定类型的构造函数列表

EventInfo[]   GetEvents();

获取指定类型的时间列

FieldInfo[]   GetFields();

获取指定类型的字段列

Type[]   GetGenericArguments();

获取与已构造的泛型类型绑定的类型参数列表,如果指定类型的泛型类型定义,则获得类型形参。对于正早构造的类型,该列表就可能同时包含类型实参和类型形参

MemberInfo[]   GetMembers();

获取指定类型的成员列表

MethodInfo[]   GetMethods();

获取指定类型的方法列表

PropertyInfo[]   GetProperties();

获取指定类型的属性列表

下面列出Type类定义的常用的只读属性

Type类定义的属性

属性

功能

Assembly   Assembly

获取指定类型的程序集

TypeAttributes   Attributes

获取制定类型的特性

Type   BaseType

获取指定类型的直接基类型

String  FullName

获取指定类型的全名

bool   IsAbstract

如果指定类型是抽象类型,返回true

bool   IsClass

如果指定类型是类,返回true

string   Namespace

获取指定类型的命名空间

   使用反射

上面的列术都是为了,这里的使用。

通过使用Type类定义的方法和属性,我们能够在运行时获得类型的各种具体信息。这是一个非常强大的功能。我们一旦得到类型信息,就可以调用其构造函数,方法,和属性。可见,反射是允许使用编译时不可用的代码的。

由于Reflection API非常多,这里不可能完整的介绍他们(这里如果完整的介绍,据说要一本书,厚书)。但是,Reflection API是按照一定逻辑设计的。因此,只要知道部分接口的使用方法,就可以举一反三的使用剩余的接口。

这里我列出四种关键的反射技术:

    1. 获取方法的信息
    2. 调用方法
    3. 构造对象
    4. 从程序集中加载类型

 获取方法的相关信息

一旦有了Type对象就可以使用GetMethodInfo()方法获取此类型支持的方法列表。该方法返回一个MethodInfo 对象数组,MethodInfo对象描述了主调类型所支持的方法,他位于System.Reflection命名空间中

MethodInfo类派生于MethodBase抽象类,而MethodBase类继承了MemberInfo类。因此我们能够使用这三个类定义的属性和方法。例如,使用Name属性得到方法名称。这里有两个重要的成员:

    1. ReturnType属性  :为Type类型的对象,能够提供方法的返回类型信息
    2. GetParameters()方法  :返回参数列表,参数信息以数组形式保存在PatameterInfo对象中。PatameterInfo类定义了大量描述参数信息的属性和方法。这里也列出两个常用的属性 :Name(包含参数名称信息的字符串),ParameterType(参数类型的信息)。

下面代码,我将使用反射获得类中所支持的方法,还有方法的信息。

View Code
复制代码
    class MyClass{int x;int y; public MyClass(int i, int j) { x = i; y = j; } public int sum() { return x + y; } public bool IsBetween(int i) { if (x < i && i < y) return true; else return false; } public void Set(int a, int b) { x = a; y = b; } public void Set(double a, double b) { x = (int)a; y = (int)b; } public void Show() { Console.WriteLine("x:{0},y:{1}",x,y); } } class ReflectDemo { static void Main(string[] args) { Type t=typeof(MyClass); //获取描述MyClass类型的Type对象 Console.WriteLine("Analyzing methods in "+t.Name); //t.Name="MyClass"  MethodInfo[] mi = t.GetMethods(); //MethodInfo对象在System.Reflection命名空间下。 foreach (MethodInfo m in mi) //遍历mi对象数组  { Console.Write(m.ReturnType.Name); //返回方法的返回类型 Console.Write(" " + m.Name + "("); //返回方法的名称  ParameterInfo[] pi = m.GetParameters(); //获取方法参数列表并保存在ParameterInfo对象数组中 for (int i = 0; i < pi.Length; i++) { Console.Write(pi[i].ParameterType.Name); //方法的参数类型名称 Console.Write(" "+pi[i].Name); // 方法的参数名 if (i + 1 < pi.Length) { Console.Write(", "); } } Console.Write(")"); Console.WriteLine(); //换行  } Console.ReadKey(); } }
复制代码

输出结果为:Analyzing methods inMyClass MyClass(int i, int j)  int sum()  bool IsBetween(int i)  void Set(int a, int b)  void Set(double a, double b)  void Show()

bool Equals(object obj)   int GetHashCode()  Type GetType()  string ToString()

注意:这里输出的除了MyClass类定义的所有方法外,也会显示object类定义的共有非静态方法。这是因为c#中的所有类型都继承于object类。另外,这些信息实在程序运行时动态获得的,并不需要预先知道MyClass类的定义

GetMethods()方法的另一种形式

这种形式可以制定各种标记,已筛选想要获取的方法。他的通用形式为:MethodInfo[] GetMethods(BindingFlags bindingAttr)

BindingFlags是一个枚举,枚举值有(很多只列出5个吧):

  1. DeclareOnly:仅获取指定类定义的方法,而不获取所继承的方法;
  2. Instance:获取实例方法
  3. NonPublic: 获取非公有方法
  4. Public: 获取共有方法
  5. Static:获取静态方法

GetMethods(BindingFlags bindingAttr)这个方法,参数可以使用or把两个或更多标记连接在一起,实际上至少要有Instance(或Static)与Public(或NonPublic)标记。否则将不会获取任何方法。

View Code
复制代码
class MyClass{int x;int y; public MyClass(int i, int j) { x = i; y = j; } private int sum() { return x + y; } public bool IsBetween(int i) { if (x < i && i < y) return true; else return false; } public void Set(int a, int b) { x = a; y = b; } public void Set(double a, double b) { x = (int)a; y = (int)b; } public void Show() { Console.WriteLine("x:{0},y:{1}",x,y); } } class ReflectDemo { static void Main(string[] args) { Type t=typeof(MyClass); //获取描述MyClass类型的Type对象 Console.WriteLine("Analyzing methods in "+t.Name); //t.Name="MyClass"  MethodInfo[] mi = t.GetMethods(BindingFlags.DeclaredOnly|BindingFlags.Instance|BindingFlags.Public); //不获取继承方法,为实例方法,为公开的 foreach (MethodInfo m in mi) //遍历mi对象数组  { Console.Write(m.ReturnType.Name); //返回方法的返回类型 Console.Write(" " + m.Name + "("); //返回方法的名称  ParameterInfo[] pi = m.GetParameters(); //获取方法参数列表并保存在ParameterInfo对象数组中 for (int i = 0; i < pi.Length; i++) { Console.Write(pi[i].ParameterType.Name); //方法的参数类型名称 Console.Write(" "+pi[i].Name); // 方法的参数名 if (i + 1 < pi.Length) { Console.Write(", "); } } Console.Write(")"); Console.WriteLine(); //换行  } Console.ReadKey(); } }
复制代码

上面例子,可以看出只显示了Myclass类显示定义的公用方法。private int sum()也不显示。

使用反射调用方法

上面我们通过反射获取到了类中的所有信息,下面我们就再使用反射调用通过反射获取到的方法。

要调用反射获取到的方法,则需要在MethodInfo实例上调用Invoke() 方法。Invoke()的使用,在下面例子中演示,说明。

下面例子是:先通过反射获取到要调用的方法,然后使用Invoke()方法,调用获取到的指定方法;

View Code
复制代码
class MyClass{int x;int y; public MyClass(int i, int j) { x = i; y = j; } private int sum() { return x + y; } public bool IsBetween(int i) { if (x < i && i < y) return true; else return false; } public void Set(int a, int b) { Console.Write("Inside set(int,int)."); x = a; y = b; Show(); } public void Set(double a, double b) { Console.Write("Inside set(double,double)."); x = (int)a; y = (int)b; Show(); } public void Show() { Console.WriteLine("x:{0},y:{1}", x, y); } } class InvokeMethDemo { static void Main() { Type t=typeof(MyClass); MyClass reflectOb = new MyClass(10, 20); reflectOb.Show(); //输出为: x:10, y:20 MethodInfo[] mi = t.GetMethods(); foreach (MethodInfo m in mi) { ParameterInfo[] pi = m.GetParameters(); if (m.Name.Equals("Set", StringComparison.Ordinal) && pi[0].ParameterType == typeof(int)) { object[] args = new object[2]; args[0] = 9; args[1] = 10; //参数reflectOb,为一个对象引用,将调用他所指向的对象上的方法,如果为静态方法这个参数必须设置为null //参数args,为调用方法的参数数组,如果不需要参数为null m.Invoke(reflectOb, args); //调用MyClass类中的参数类型为int的Set方法,输出为Inside set(int,int).x:9, y:10  } } Console.ReadKey(); } }
复制代码

获取Type对象的构造函数

在这之前的阐述中,由于MyClass类型的对象是都是显式创建的,因此使用反射技术调用MyClass类中的方法是没有任何优势的,还不如以普通方式调用方便简单呢。但是,如果对象是在运行时动态创建的,反射功能的优势就会显示出来。在这种情况下,要先获取一个构造函数列表,然后调用列表中的某个构造函数,创建一个该类型的实例。通过这种机制,可以在运行时实例化任意类型的对象,而不必在声明语句中指定类型。

View Code
复制代码
class MyClass{int x;int y; public MyClass(int i) { x = y + i; } public MyClass(int i, int j) { x = i; y = j; } public int sum() { return x + y; } } class InvokeConsDemo { static void Main() { Type t = typeof(MyClass); int val; ConstructorInfo[] ci = t.GetConstructors(); //使用这个方法获取构造函数列表 int x; for (x = 0; x < ci.Length; x++) { ParameterInfo[] pi = ci[x].GetParameters(); //获取当前构造函数的参数列表 if (pi.Length == 2) break; //如果当前构造函数有2个参数,则跳出循环  } if (x == ci.Length) { return; } object[] consargs = new object[2]; consargs[0] = 10; consargs[1] = 20; object reflectOb = ci[x].Invoke(consargs); //实例化一个这个构造函数有两个参数的类型对象,如果参数为空,则为null //实例化后,调用MyClass中的方法 MethodInfo[] mi = t.GetMethods(BindingFlags.Public | BindingFlags.DeclaredOnly | BindingFlags.Instance); foreach (MethodInfo m in mi) { if (m.Name.Equals("sum", StringComparison.Ordinal)) { val = (int)m.Invoke(reflectOb, null); //由于实例化类型对象的时候是用的两个参数的构造函数,所以这里返回的结构为30 Console.WriteLine(" sum is " + val); //输出 sum is 30  } } Console.ReadKey(); } }
复制代码

从程序集获得类型

在这之前的阐述中可以看出一个类型的所有信息都能够通过反射得到,但是MyClass类型本身,我们却没有做出获取。虽然前面的阐述实例,可以动态确定MyClass类的信息,但是他们都是基于以下事实:预先知道类型名,并且在typeof语句中使用它获得Type对象。尽管这种方式可能在很多种情况下都很管用,但是要发挥反射的全部功能,我们还需要分析程序集的内容来动态确定程序的可用类型。

借助Reflection API,可以加载程序集,获取它的相关信息并创建其公共可用类型的实例。通过这种机制,程序能够搜索其环境,利用潜在功能,而无需在编译期间显式的定义他们。这是一个非常有效,且令人兴奋的概念。

为了说明如何获取程序集中的类型,我创建两个文件。第一个文件定义一组类,第二个文件则反射各个类的信息。 代码效果如下。

1.这下面代码是要编译生成MyClass.exe文件的

View Code
复制代码
 class MyClass{int x;int y; public MyClass(int i) { x = y + i; } public MyClass(int i, int j) { x = i; y = j; } public int sum() { return x + y; } } class Demo { static void Main() { Console.WriteLine("hello word !"); Console.ReadKey(); } }
复制代码

2.这下面的代码是获取上面生成程序集的

View Code
复制代码
 class Class3{static void Main() {Assembly asm = Assembly.LoadFrom(@"C:\Users\lenovo\Documents\visual studio 2010\Projects\Reflection_test\ConsoleApplication1\bin\Debug\MyClass.exe"); //加载指定的程序集 Type[] alltype = asm.GetTypes(); //获取程序集中的所有类型列表 foreach (Type temp in alltype) { Console.WriteLine(temp.Name); //打印出MyClass程序集中的所有类型名称 MyClass , Demo  } Console.ReadKey(); } }
复制代码

上面获取到了,程序集中的类型,如果想操作程序集中类型中的方法,则跟前边我们累述的方法是一个样子的。

相关文章:

C# 多网卡 Server Listen

VC和BCB中做一个Server的监听程序,只需要指定端口,然后监听(Listen)就行了.在C#找不到这个函数了,慢慢看MSDN,怎么需要指定IP和Port才能监听,那么多网卡的机器应该怎么写程序呢?下面的程序可以解释怎么去做. TcpListener 类别会提供简易的方法&#xff0c;用以在封锁的同步模式…

赠书 | 一文了解预训练语言模型

来源 | 博文视点头图 | 下载于视觉中国近年来&#xff0c;在深度学习和大数据的支撑下&#xff0c;自然语言处理技术迅猛发展。而预训练语言模型把自然语言处理带入了一个新的阶段&#xff0c;也得到了工业界的广泛关注。通过大数据预训练加小数据微调&#xff0c;自然语言处理…

写了六个相同功能的函数之后,我学到了什么

本文讲的是写了六个相同功能的函数之后&#xff0c;我学到了什么&#xff0c;几周之前&#xff0c;一个社区在 Free Code Camp’s Forum 上发起了非官方的算法大赛。 这个题目看似很简单&#xff1a;返回小于数字 N 的所有 3 或者 5 的倍数的和&#xff0c;N 是函数的参数。 但…

libevent介绍

libevent是一款事件驱动的网络开发包 由于采用 c 语言开发 体积小巧&#xff0c;跨平台&#xff0c;速度极快。 通常我们在建立服务器的处理模型的时候,主要是下面集中模型;(1) a new Connection 进来&#xff0c;用 fork() 产生一个 Process 处理。 (2) a new Connecti…

蓝色起源载人火箭7月首飞,贝索斯即将实现儿时愿望

整理 | 寇雪芹出品 | AI 科技大本营&#xff08;ID:rgznai100&#xff09;头图 | 下载于ICphoto美国当地时间6月7日早&#xff0c;亚马逊创始人、世界首富贝索斯&#xff08;Jeff Bezos&#xff09;在社交媒体上发帖表示&#xff0c;自己将在7月20日乘坐蓝色起源&#xff08;Bl…

使用jquery.more.js来实现点击底部更多后, 底部加载出新的数据

<div class"bus-nav-bar ft12"><div class"navt bor-r-c pos-rel {if $int 0}fwbold{/if}"><a href"portal.php?modmerchant&actionvoucherlist&int0">全部订单</a><em class"pos-abs"></…

ios开发学习-手势交互(Gesture)效果源码分享

qianqianlianmengios开发学习-手势交互&#xff08;Gesture&#xff09;效果源码分享 All Around Pull View 介绍&#xff1a;实现视图四个方向&#xff08;上下左右&#xff09;都能够拖动更新&#xff08;pull to refresh&#xff09;。 编译测试&#xff0c;测试环境…

通过C#实现集合类纵览.NET Collections及相关技术

概述&#xff1a;在真正的对象化开发项目中&#xff0c;我们通常会将常用的业务实体抽象为特定的类&#xff0c;如Employee、Customer、Contact等&#xff0c;而多数的类之间会存在着相应的关联或依存关系&#xff0c;如Employee和Customer通过Contact而产生关联、Contact是依赖…

TIOBE 6 月榜单: Python 有望超越 C 语言成为第一名

整理 | 苏宓出品 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;头图 | 下载于ICphotoTIOBE 官方最新发布了 6 月的编程语言榜单&#xff0c;这个月榜单中又有怎样的发展趋势&#xff1f;Python 有望成为第一名在本月榜单中&#xff0c;位居第二名的 Python 与第一名 C…

使用dom4j解析XML例子

包括三个文件&#xff1a;studentInfo.xml(待解析的xml文件), Dom4jReadExmple.java(解析的主要类), TestDom4jReadExmple.java(测试解析的结果) 代码运行前需先导入dom4j架包。 studentInfo.xml文件&#xff08;该文件放在本项目目录下&#xff09;内容如下&#xff1a; <?…

mkdir、rmdir命令、head、tail命令

mkdir-p 递归创建目录11里面都是空目录rmdir删除空目录 -p 当子目录被删除后使它也成为空目录的话&#xff0c;则一并删除步骤&#xff1a;先删除11/22/33 发现22目录空了&#xff0c;因为33删了&#xff0c;于是再删22&#xff0c;空了再删11head默认是前10行 –n指定几行tai…

Linux Find 命令精通指南

作者&#xff1a;Sheryl Calish Linux find 命令是所有 Linux 命令中最有用的一个&#xff0c;同时也是最混乱的一个。它很难&#xff0c;因为它的语法与其他 Linux 命令的标准语法不同。但是&#xff0c;它很强大&#xff0c;因为它允许您按文件名、文件类型、用户甚至是时间戳…

【安全运维】 linux 系统账户,网络,简易安全加固方案(第一部分),经测试可行...

前言讲到linux系统账户的管理以及安全&#xff0c;就必须涉及 /etc/passwd /etc/shadow 这2个文件这里以截图中文字说明的方式&#xff0c;来分析这2个文件的内容&#xff0c;并且给出一些实用的安全加固方案注意&#xff0c;本文会持续更新&#xff0c;后续加入的内容都以直…

不用深度学习,怎么提取图像特征?

来源 | 小白学视觉头图 | 下载于ICphoto图像分类是数据科学中最热门的领域之一&#xff0c;在本文中&#xff0c;我们将分享一些将图像转换为特征向量的技术&#xff0c;可以在每个分类模型中使用。VATboxVATbox&#xff0c;作为n一个我们所暗示的&#xff0c;涉及增值税问题&a…

课程第五天内容《基础交换 五》

2019独角兽企业重金招聘Python工程师标准>>> 以太网/LAN(local area network )的相关概念&#xff1a; 问题&#xff1a; 信号传输距离有限&#xff1b; 解决方案&#xff1a; 中继器 - 放大电信号&#xff0c;延长信息的传输距离&#xff1…

C#综合揭秘——Entity Framework 并发处理详解

引言 在软件开发过程中&#xff0c;并发控制是确保及时纠正由并发操作导致的错误的一种机制。从 ADO.NET 到 LINQ to SQL 再到如今的 ADO.NET Entity Framework&#xff0c;.NET 都为并发控制提供好良好的支持方案。 并发处理方式一般分为乐观必并发与悲观必并发两种&#xff0…

@2021高考生,用 Python 分析专业“钱景”

来源 | 关于数据分析于可视化头图 | 下载于ICphoto2021年的高考在昨日拉开帷幕&#xff0c;十年的寒窗苦读&#xff0c;终于到了最后见分晓的时候了。在这么一场关键的考试当中&#xff0c;除了考试前努力奋斗&#xff0c;考场上认真答题&#xff0c;考后的志愿填报也是极其的重…

Linux下C语言的fgets与fputs

使用的是 CentOS gcc编译下面程序 显示warning: the gets function is dangerous and should not be used.问题出在程序中使用了 gets Linux 下gcc编译器不支持这个函数&#xff0c;解决办法是使用 fgets fgets()函数的基本用法为&#xff1a; fgets(char * s,int size,FILE * …

linux发行版的用户交互

1 cli&#xff0c;即command line interface 纯命令行的交互方式&#xff0c;该命令行界面是由shell提供的。 linux内核本身也自带了一个console&#xff0c;即linux console&#xff0c;它是基于frame buffer的。 cli的界面都是基于ncurses库开发的。 2 GUI&#xff0c;graphi…

C#中在应用程序和DLL使用消息

在C#中采用的是事件驱动方式&#xff0c;但在我们使用的过程中&#xff0c;有时候通过调用系统原有的消息&#xff0c;处理起来会比较简单一些&#xff0c;特别是在处理与DLL文件的交互时&#xff0c;的确是非常的方便。 在C#中使用自定义消息 在C#中使用自定义消息非常简单&…

倪光南院士:openEuler与全球开发者共同推动计算产业发展

今日&#xff0c;以“创造最好的OS&#xff0c;成就更好的我们”为主题的 openEuler Developer Day 2021在北京成功举行。本次大会由openEuler社区发起&#xff0c;产业组织专家、学者、企业领袖和开发者们围绕多样性计算、云原生全栈、全场景协同等技术方向共同探讨和创新。大…

jhello框架-ajax

2019独角兽企业重金招聘Python工程师标准>>> 现在的web开发没有ajax都没法活&#xff0c;所以在jhello中实现了一个简单的ajax交互&#xff0c;使用json作为载体。 在上篇《交互》中讲到一种交互的方式是把数据放入Model中&#xff0c;通过ModelAndView类返回到视图…

发微信模版消息换行用\n

发微信模版消息换行用\n发微信模版消息换行用\n发微信模版消息换行用\n发微信模版消息换行用\n发微信模版消息换行用\n转载于:https://blog.51cto.com/xuqin/1974131

二次元会让人脸识别失效吗?

来源 | PyTorch 开发者社区责编 | 寇雪芹头图 | 下载于ICphoto人脸识别也遇到坑了&#xff0c;识别得了三次元&#xff0c;却对二次元无效。迪士尼的技术团队&#xff0c;正在开发这一算法&#xff0c;以帮助动画制作者进行后期搜索。团队利用 PyTorch&#xff0c;效率得到很大…

基于第四层交换技术的负载均衡

摘 要 本文介绍了第四层交换技术的概念&#xff0c;技术原理以及如何使用第四层交换技术实现远程教育系统中的应用服务器负载均衡。 作者&#xff1a; 凌仲权&#xff0c;现就读于西安电子科技大学&#xff0c;2001级硕士研究生。主要的科研方向为计算机网络技术研究以及远程教…

開始Unity3D的学习之旅

前言&#xff1a;这个系列的文章纯属对自己学习的整理&#xff0c;非高手之作。但确实的记载了我作为一个没接触过3D游戏编程的大学生的心路历程。争取每周整理一次吧。之所以会開始学Unity3D&#xff0c;最基本的原因是由于在快放暑假的时候&#xff0c;我找了一家做iPhone游戏…

linux 定时任务crond

1.定时任务crond 1.1 crond是什么 crond是linux系统中用来定期执行命令或指定程序任务的一种服务或软件。特殊需求&#xff1a;&#xff08;秒级别&#xff09;crond服务就无法搞定了&#xff0c;一般工作中写脚本守护进程执行。 为什么要使用crond定时任务&#xff1a; linux系…

用C#去除代码的SourceSafe管理

经常看一些的程序&#xff0c;有些一个解决方案带有多个项目&#xff0c;由于代码比较多&#xff0c;多人开发&#xff0c;所以好多vs.net下的工程是用source safe进行版本控制的。而用source safe进行版本控制需要局域网路径共享&#xff0c;因此好多项目换一台机器打开会出现…

用jarsigner对android apk进行签名

以前对apk重新打包签名都是用的apktool里面的Auto-sign 工具&#xff0c;后来发现有时候利用该工具对一些apk签名会失败&#xff0c;所以后来就使用 jarsigner这个工具&#xff0c;现记录一下这个工具的使用方法1 首先要生成一个自己的keyD:\>keytool -genkey -alias myKey…