1.反射
在.NET中,反射(reflection)是一个运行库类型发现的过程.通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。
(1)命名空间
(2)一些在发射中经常用到的类
Assembly类
Assembly类是可重用、无版本冲突并且可自我描述的公共语言运行库应用程序构造块。可以使用Assembly.Load和Assembly.LoadFrom方法动态地加载程序集。
Type类
反射的中心是System.Type类。System.Type类是一个抽象类,代表公用类型系统中的一种类型。这个类使您能够查询类型名、类型中包含的模块和名称空间、以及该类型是一个数值类型还是一个引用类型。
System.Type类使您能够查询几乎所有与类型相关的属性,包括类型访问限定符、类型是否、类型的COM属性等等。
获取给定类型的Type引用有3种常用方式:
●使用 C# typeof 运算符。
Type t = typeof(string);
●使用对象GetType()方法。
string s = "grayworm";
Type t = s.GetType();
●还可以调用Type类的静态方法GetType()。
Type t = Type.GetType("System.String");
Activator类
Activator类支持动态创建.NET程序集和COM对象。可以通过CreateComInstanceFrom、CreateInstance、CreateInstanceFrom、GetObject四个静态方法加载COM对象或者程序集,并能创建指定类型的实例。
Binder类
Binder类是一个用于执行类型转换的绑定器,Type对象的InvokeMember方法接受Binder对象,这个对象描述了如何将传递给InvokeMember的参数转换成方法实际需要的类型。
Binder类是一个抽象类,要创建绑定器,需要重写方法BindToMethod、BindToField、SelectMehtod、SelectProperty和ChangeType。
DefaultMemberAttribute类
DefaultMemberAttribute类用于类型并带有一个指明默认成员名称的字符串参数。能够通过InvokeMember调用默认成员,而不需要传递调用成员的名称。当需要绑定器但不需要特别的绑定行为时就可以使用它。
其它
还有一些对元素类型信息描述的类,ConstrutorInfo(构造函数)、MethodInfo(方法)、FieldInfo(字段)、PropertyInfo(属性)、EventInfo(事件)、MemberInfo(成员)、ParameterInfo(参数)。如果查询得到了具有任何类型信息的实例,就可以获得该类型中任意元素的类型信息,当然出于安全原因,不保证会得到程序集中的任何信息。
例子:
首先我们先建立一个类库工程MyDll,并新建一个类ReflectTest
using System;
namespace MyDll
{
/**//// <summary>
/// ReflectTest 的摘要说明。
/// </summary>
//接口
public interface ITest
{
int add();
}
public class ReflectTest : ITest
{
public String Write;
private String Writec;
public int add()
{
return 10;
}
public String Writea
{
get { return Write;}
set { Write = value;}
}
private String Writeb
{
get { return Writec;}
set { Writec = value;}
}
//构造函数
public ReflectTest()
{
this.Write = "Write";
this.Writec = "Writec";
}
//有参构造函数
public ReflectTest(string str1,string str2)
{
this.Write = str1;
this.Writec = str2;
}
public string PrintString(string s)
{
return "这是一个实例方法" + s;
}
private string PrintString2()
{
return "这是一个私有方法";
}
public static string Print(string s)
{
return "这是一个静态方法," + s;
}
public string PrintNoPara()
{
return "您使用的是无参数方法";
}
public static string PrintData(string s)
{
return s;
}
public static string PrintData(string s1, string s2)
{
return s1+s2;
}
}
}
编译后得到MyDll.dll文件,应用反射
using System;
using System.Reflection;
namespace cmdText
{
/**//// <summary>
/// 说明:反射学习
/// 程序:寻梦E.net
/// </summary>
public class Reflect2
{
delegate string TestDelegate(string value1);
public static void Main(string[] args)
{
Assembly ass = null ;
Type type = null ;
object obj = null;
string assemblyName = "MyDll";
string className = "MyDll.ReflectTest";
try
{
//以下三种方法都可以
//ass = Assembly.LoadFile(System.Environment.CurrentDirectory+"/MyDll.dll");
//ass = Assembly.LoadFrom(System.Environment.CurrentDirectory+"/MyDll.dll");
ass = Assembly.Load(assemblyName);
}
catch
{
Console.Write("无法找到程序集!");
return;
}
//获取类型
type = ass.GetType(className);
//type = Type.GetType(className);//效果同上
//生成一个类实例,无参构造函数
obj = ass.CreateInstance(className);
//obj = Activator.CreateInstance(type);//效果同上
//**************************方法调用*************************************
//反射实例方法
Console.WriteLine("*******方法调用**************************************");
MethodInfo method = type.GetMethod("PrintString");
string s = (string)method.Invoke(obj,new string[]{"寻梦E.net"});
Console.WriteLine(s);
//反射私有方法
method = type.GetMethod("PrintString2",BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
s = (string)method.Invoke(obj,null);
Console.WriteLine(s);
//反射静态方法
method = type.GetMethod("Print");
s = (string)method.Invoke(null,new string[]{"寻梦E.net"});
Console.WriteLine(s);
//反射无参方法
method = type.GetMethod("PrintNoPara");
s = (string)method.Invoke(obj,null);
Console.WriteLine(s);
//反射重载了的静态方法
Type[] objParam = {typeof(string),typeof(string)};
method = type.GetMethod("PrintData",objParam );
s = (string)method.Invoke(null,new object[]{"hello!"," 寻梦E.net"});
Console.WriteLine(s);
Console.WriteLine("*******属性,域的赋值与访问***********************");
//*****************属性,域的赋值与访问***************************************
//公有属性
PropertyInfo pi1 = type.GetProperty("Writea");
pi1.SetValue(obj, "公有属性:Writea", null);
Console.WriteLine(pi1.GetValue(obj,null));
//私有属性
PropertyInfo pi2 = type.GetProperty("Writeb", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
pi2.SetValue(obj, "私有属性:Writeb", null);
Console.WriteLine(pi2.GetValue(obj, null));
//域
FieldInfo fi1 = type.GetField("Write");
Console.WriteLine(fi1.GetValue(obj));
Console.WriteLine("*******类型,模块,方法,构造函数等信息的获取*****");
//******************类型,模块,方法,构造函数等信息的获取******************************************
//有参构造函数实例化
//string[] classParams = {"lsm","sky"};
//object obj2 = Activator.CreateInstance(type,classParams);
foreach(Type t in ass.GetTypes())
{
Console.WriteLine("类型:"+t.Name );
}
foreach(Module m in ass.GetModules())
{
Console.WriteLine("模块:"+m.Name);
}
MethodInfo[] methods = type.GetMethods();
foreach (MethodInfo m in methods)
{
Console.WriteLine("方法"+m.Name); //显示所有的共有方法
}
FieldInfo[] fields = type.GetFields();
foreach (FieldInfo f in fields)
{
Console.WriteLine("字段信息:"+f.Name);
}
PropertyInfo[] propertys = type.GetProperties();
foreach( PropertyInfo p in propertys)
{
Console.WriteLine("属性:"+p.Name);
}
ConstructorInfo[] ci1 = type.GetConstructors();
foreach (ConstructorInfo ci in ci1)
{
Console.WriteLine("构造函数:"+ci.ToString()); //获得构造函数的形式
}
//*******************接口***************************************
Console.WriteLine("*******接口*****************************************");
MyDll.ITest obj1 = (MyDll.ITest)ass.CreateInstance(className);//这里必须是实现接口的类名,因为接口不能实例化
//MyDll.ReflectTest obj2= (MyDll.ReflectTest)ass.CreateInstance(className);
//典型的工厂模式
int i = obj1.add();
Console.WriteLine(i);
//*****************委托*******************************************
TestDelegate myDelegate = (TestDelegate)Delegate.CreateDelegate(typeof(TestDelegate), obj, "PrintString");
//动态创建委托的简单例子
Console.WriteLine(myDelegate(" 动态调用委托"));
//*****************获得解决方案的所有Assembly********************
Assembly[] assemblys = AppDomain.CurrentDomain.GetAssemblies();
//遍历显示每个Assembly的名字
foreach (object var in assemblys)
{
Console.WriteLine("所有的Assembly的名字:"+var.ToString());
}
Console.Read();
}
}
}
2.Attribute(特性)
MADN的定义为:公共语言运行时允许添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型、字段、方法和属性等。Attributes和Microsoft .NET Framework文件的元数据(metadata)保存在一起,可以用来向运行时描述你的代码,或者在程序运行的时候影响应用程序的行为。
Attribute就是一种“附着物”——就像牡蛎吸附在船底或礁石上一样。这些附着物的作用是为它们的附着体追加上一些额外的信息(这些信息就保存在附着物的体内)——比如“这个类是我写的”或者“这个函数以前出过问题”等等。
你可能会问:这跟注释有什么区别呢?
当然有区别啦!注释是对程序源代码的一种说明,主要目的是给人看的,在程序被编译的时候会被编译器所丢弃,因此,它丝毫不会影响到程序的执行。而Attribute是程序代码的一部分,不但不会被编译器丢弃,而且还会被编译器编译进程序集(Assembly)的元数据(Metadata)里,在程序运行的时候,你随时可以从元数据里提取出这些附加信息来决策程序的运行。
例子:
自定义Attribute类:VersionAttribute
[AttributeUsage(AttributeTargets.Class)]
public class VersionAttribute : Attribute
{
public string Name { get; set; }
public string Date { get; set; }
public string Describtion { get; set; }
}
使用自定义Attribute的Class:
[Version(Name = "hyddd", Date = "2009-07-20", Describtion = "hyddd's class")]
public class MyCode
{
//...
}
上面这个Class中的Attribute一般会被如何使用呢?
class Program
{
static void Main(string[] args)
{
var info = typeof(MyCode);
var classAttribute = (VersionAttribute)Attribute.GetCustomAttribute(info, typeof(VersionAttribute));
Console.WriteLine(classAttribute.Name);
Console.WriteLine(classAttribute.Date);
Console.WriteLine(classAttribute.Describtion);
}
}