1.反射的作用
简单来说,反射提供了如下几种能力:
1. 查看和遍历类型和成员的基本信息以及程序集元数据
2. 迟绑定属性和方法
3. 动态创建实例
2.获取Type的三种方式
反射的核心是Type类,这个类封装了关于对象的信息,也是进行反射的入口。当你获得了关于类型的Type对象后,就可以根据Type提供的属性和方法获取这个类型的一切信息(方法、字段、属性、事件、参数、构造函数等)。
2.1 通过静态方法GetType获取
Console.WriteLine(Type.GetType("System.String"));
2.2 通过typeof获取
Console.WriteLine(typeof(int).ToString());
2.3通过类型实例获取
string str=string.Empty;
Console.WriteLine(str.GetType().ToString());
3.Type类型信息
Type提供了下列属性获得基本信息:
对照上面的列表,类似的还有 PropertyInfo类型、ConstructorInfo类型、MethodInfo类型、EventInfo类型。而对于方法而言,对于它的参数,也会有in参数,out参数,参数类型等信息,类似的,在 System.Reflection 命名空间下,除了有上面的提到的那么多Info后缀结尾的类型,还有个ParameterInfo 类型,用于封装方法的参数信息。
最后,应该注意到 Type 类型,以及所有的Info类型均 继承自 MemberInfo 类型,MemberInfo类型提供了获取类型基础信息的能力。
由于MemberInfo是一个基类,当我们获得一个MemberInfo后,我们并不知道它是PropertyInfo(封装了属性信息的对象)还是FieldInfo(封装了属性信息的对象),所以,有必要提供一个办法可以让我们加以判断
[Flags]
public enum MemberTypes {
Constructor = 1, // 该成员是一个构造函数
Event = 2, // 该成员是一个事件
Field = 4, // 该成员是一个字段
Method = 8, // 该成员是一个方法
Property = 16, // 该成员是一个属性
TypeInfo = 32, // 该成员是一种类型
Custom = 64, // 自定义成员类型
NestedType = 128, // 该成员是一个嵌套类型
All = 191, // 指定所有成员类型。
}
4.反射程序集
加载程序集一般有几种方式:
- 直接写”文件名.dll”的全路径
Assembly asm = Assembly.LoadFrom(@"C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Web.dll");
- 写程序集名称,不用写后缀
Assembly asm = Assembly.Load("Demo");
- 获取当前程序集
Assembly as = Assembly.GetExecutingAssembly();
- 通过type类型实例加载
Type t = typeof(int)
Assembly asm = t.Assembly;
4.1 准备Demo
为了方便进行我们后面的测试,我们现在建立一个Windows控制台应用程序,我给它起名叫SimpleExplore;然后再添加一个Demo类库项目,我们将来编写的代码就用户查看这个Demo项目集的类型信息 或者 是对这个程序集中的类型进行迟绑定。这个Demo项目只包含一个命名空间Demo,为了体现尽可能多的类型,其代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Demo
{
public abstract class BaseClass
{
}
public struct DemoStruct { }
public delegate void DemoDelegate(Object sender, EventArgs e);
public enum DemoEnum
{
terrible, bad, common = 4, good, wonderful = 8
}
public interface IDemoInterface
{
void SayGreeting(string name);
}
public interface IDemoInterface2 { }
public sealed class DemoClass : BaseClass, IDemoInterface, IDemoInterface2
{
private string name;
public string city;
public readonly string title;
public const string text = "Const Field";
public event DemoDelegate myEvent;
public string Name
{
private get { return name; }
set { name = value; }
}
public DemoClass()
{
title = "Readonly Field";
}
public class NestedClass { }
public void SayGreeting(string name)
{
Console.WriteLine("Morning :" + name);
}
}
}
SimpleExplore控制台程序中编写AssemblyExplore方法(SimpleExplore控制台程序记得引用Demo类库):
public static void AssemblyExplore()
{
System.Reflection.Assembly asm = System.Reflection.Assembly.Load("Demo");
Console.WriteLine("FullName(程序集全名称):"+asm.FullName);
Console.WriteLine("Location(完整路径):" + asm.Location);
//获得程序集定义的类型
Type[] types= asm.GetTypes();
foreach (var item in types)
{
Console.WriteLine("类型:"+item.ToString());
}
}
输出结果:
5.反射基本信息(Isxxx)
编写方法TypeExplore
/// <summary>
/// 获得基本信息(Isxxx)
/// </summary>
/// <param name="t"></param>
public static void TypeExplore(Type t)
{
Console.WriteLine("名称:"+t.Name);
Console.WriteLine("全名称:" + t.FullName);
Console.WriteLine("所属名称空间:" + t.Namespace);
Console.WriteLine("基类型:"+t.BaseType);
Console.WriteLine("CLR提供的类型:"+t.UnderlyingSystemType);
Console.WriteLine("特性:" + t.Attributes);
Console.WriteLine("值类型:" + t.IsValueType);
Console.WriteLine("枚举类型:" + t.IsEnum);
Console.WriteLine("类:" + t.IsClass);
Console.WriteLine("数组类型:" + t.IsArray);
Console.WriteLine("接口类型:" + t.IsInterface);
Console.WriteLine("指针类型:" + t.IsPointer);
Console.WriteLine("密封类型:" + t.IsSealed);
Console.WriteLine("基类类型:" + t.IsPrimitive);
Console.WriteLine("抽象类型:" + t.IsAbstract);
Console.WriteLine("公开类型:" + t.IsPublic);
Console.WriteLine("不公开类型:" + t.IsNotPublic);
Console.WriteLine("程序集之外的代码是否可访问:" + t.IsVisible);
Console.WriteLine("引用传递:" + t.IsByRef);
}
6.获得类型成员信息(Getxxxs)
/// <summary>
/// 获得类型成员信息(Getxxxs)
/// </summary>
/// <param name="t"></param>
public static void MemberExplore(Type t)
{
foreach (System.Reflection.MemberInfo item in t.GetMembers())
{
Console.WriteLine("成员:{0}\t 类型:{1}",item.ToString().PadRight(40),item.MemberType.ToString());
}
}
都是聪明人,后面什么GetEvents,GetProperties、GetFields等等就不做过多介绍了
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SimpleExplore
{
class Program
{
static void Main(string[] args)
{
AssemblyExplore();
Console.WriteLine("=================================================");
TypeExplore(typeof(Demo.DemoClass));
Console.WriteLine("=================================================");
MemberExplore(typeof(Demo.DemoClass));
}
/// <summary>
/// 获得类型成员信息(Getxxxs)
/// </summary>
/// <param name="t"></param>
public static void MemberExplore(Type t)
{
foreach (System.Reflection.MemberInfo item in t.GetMembers())
{
Console.WriteLine("成员:{0}\t 类型:{1}",item.ToString().PadRight(40),item.MemberType.ToString());
}
}
/// <summary>
/// 获得基本信息(Isxxx)
/// </summary>
/// <param name="t"></param>
public static void TypeExplore(Type t)
{
Console.WriteLine("名称:"+t.Name);
Console.WriteLine("全名称:" + t.FullName);
Console.WriteLine("所属名称空间:" + t.Namespace);
Console.WriteLine("基类型:"+t.BaseType);
Console.WriteLine("CLR提供的类型:"+t.UnderlyingSystemType);
Console.WriteLine("特性:" + t.Attributes);
Console.WriteLine("值类型:" + t.IsValueType);
Console.WriteLine("枚举类型:" + t.IsEnum);
Console.WriteLine("类:" + t.IsClass);
Console.WriteLine("数组类型:" + t.IsArray);
Console.WriteLine("接口类型:" + t.IsInterface);
Console.WriteLine("指针类型:" + t.IsPointer);
Console.WriteLine("密封类型:" + t.IsSealed);
Console.WriteLine("基类类型:" + t.IsPrimitive);
Console.WriteLine("抽象类型:" + t.IsAbstract);
Console.WriteLine("公开类型:" + t.IsPublic);
Console.WriteLine("不公开类型:" + t.IsNotPublic);
Console.WriteLine("程序集之外的代码是否可访问:" + t.IsVisible);
Console.WriteLine("引用传递:" + t.IsByRef);
}
/// <summary>
/// 获得程序集信息
/// </summary>
public static void AssemblyExplore()
{
System.Reflection.Assembly asm = System.Reflection.Assembly.Load("Demo");
Console.WriteLine("FullName(程序集全名称):"+asm.FullName);
Console.WriteLine("Location(完整路径):" + asm.Location);
//获得程序集定义的类型
Type[] types= asm.GetTypes();
foreach (var item in types)
{
Console.WriteLine("类型:"+item.ToString());
}
}
}
}