天天看点

C#反射机制详解



反射的定义:审查元数据并收集关於它的类型信息的能力,元数据(编辑后的基本数据单元)就是一大堆表,编译器会创建一个类定义表,一个字段定义表,一个方法定义表等,System.Reflection命名空间包含的几个类,允许你反射(解析)这些元数据的代码

一、反射的作用:

动态的创建类型的实例,将类型邦定到现有对象,或从现有对象中获取类型

应用程序需要在运行时从某个特定的程序集中载入一个特定的类型,以便实现某个任务时可以用到反射

反射主要应用於类库,这些类库需要知道一个类型的定义,以便提供更多的功能

二、应用要点:

现实应用程序中很少使用到反射

使用反射动态邦定需要牺牲性能

有些元数据信息是不能通过反射获取的

某些反射类型是专门為那些CLR开发编辑器开发使用的,所以你要意思到不是所有反射类型都是可以使用的

三、取得Assembly的方法:

Assembly.Load

Assembly.LoadFile

Assembly.LoadFrom

Type对象的Assembly方法

四、反射的成员:

MemberInfo-成员

ConstructorInfo-结构

FieldInfo-字段

MethodInfo-方法

PropertyInfo-属性

EventInfo-事件

五、根据反射取得对象的Member信息

private void WriteReflectionInfo()

{

Type testType = typeof(Test);

Assembly assembly = testType.Assembly;

Response.Write("Assembly:" + assembly.FullName + "<br/>");

Type[] typeList = assembly.GetTypes();   // 获取类型

// 针对每个类型获取详细信息

foreach (Type type in typeList)

{

    Response.Write("------------------------" + type.Namespace + type.Name + "------------------------<br/>");

    // 获得类型的结构信息

    ConstructorInfo[] constructs = type.GetConstructors();

    // 获得类型的字段信息

    FieldInfo[] fields = type.GetFields();

    Response.Write("<b>类的公共字段信息如下:</b>" + "<br/>");

    int a1 = 1;

    foreach (FieldInfo field in fields)

    {

        Response.Write((a1++).ToString() + ". " + field.Name + "<br/>");

    }

    // 获得方法信息

    MethodInfo[] methods = type.GetMethods();

    Response.Write("<b>类的公共方法如下:</b>" + "<br/>");

    int a2 = 1;

    foreach (MethodInfo method in methods)

    {

        ParameterInfo[] parameters = method.GetParameters();

        ParameterInfo reparam = method.ReturnParameter;

        Response.Write((a2++).ToString() + ". " + reparam.ParameterType.Name + " " + method.Name + "(");

        int index = 0;

        foreach (ParameterInfo para in parameters)

        {

            if (index++ < parameters.Length - 1)

                Response.Write(para.ParameterType.Name + " " + para.Name + ",");

            else

                Response.Write(para.ParameterType.Name + " " + para.Name);

        }

        Response.Write(")<br/>");

    }

    // 获得属性的信息

    PropertyInfo[] propertys = type.GetProperties();

    Response.Write("<b>类的公共属性如下:</b>" + "<br/>");

    int a3 = 1;

    foreach (PropertyInfo pro in propertys)

    {

        Response.Write((a3++).ToString() + ". " + pro.PropertyType.Name + " " + pro.Name + "{");

        if (pro.CanRead) Response.Write("get;");

        if (pro.CanWrite) Response.Write("set;");

        Response.Write("}<br/>");

    }

    // 获得事件信息

    EventInfo[] events = type.GetEvents();

    Response.Write("<b>类的成员如下:</b>" + "<br/>");

    // 获得成员

    int a4 = 1;

    foreach (MemberInfo mi in type.GetMembers())

    {

        Response.Write((a4++).ToString() + ". " + mi.MemberType.ToString() + " : " + mi.Name + "<br/>");

    }

}

六、动态创建对象

Assembly对象的 CreateInstance方法

Activator. CreateInstance方法

Type对象的 InvokeMember方法

// 使用Assembly的CreateInstance方法来取得对象的实例

private void Assembly_CreateInstance()

{

    string assemblyName = "SqlModel";

    string className = assemblyName + ".Member";

    // 创建无参数实例

    IDAL.IMember member = (IDAL.IMember)Assembly.Load(assemblyName).CreateInstance(className);

    Response.Write("创建无参数实例:" + member.ID + "<br/>");

    // 创建有参数实例

    Object[] parameters = new Object[1];

    parameters[0] = 10000;

    IDAL.IMember member1 = (IDAL.IMember)Assembly.Load(assemblyName).CreateInstance(className, false, BindingFlags.Default, null, parameters, null, null);

    Response.Write("创建有参数实例:" + member1.ID + "<br/>");

}

// 使用Activator的CreateInstance方法来取得对象的实例

private void Activator_CreateInstance()

{

    string assemblyName = "SqlModel";

    string className = assemblyName + ".Member";

    // 创建无参数实例

    System.Runtime.Remoting.ObjectHandle obj = Activator.CreateInstance(assemblyName, className);

    IDAL.IMember member = (IDAL.IMember)obj.Unwrap();

    Response.Write("创建无参数实例:" + member.ID + "<br/>");

    // 创建有参数实例

    Object[] parameters = new Object[1];

    parameters[0] = 10000;

    System.Runtime.Remoting.ObjectHandle obj1 = Activator.CreateInstance(assemblyName, className, false, BindingFlags.CreateInstance, null, parameters, null, null, null);

    IDAL.IMember member1 = (IDAL.IMember)obj1.Unwrap();

    Response.Write("创建有参数实例:" + member1.ID + "<br/>");

}

// 使用Type的InvokeMember方法来取得对象的实例

private void Type_InvokeMember()

{

    string assemblyName = "SqlModel";

    string className = assemblyName + ".Member";

    Assembly assem = Assembly.Load(assemblyName);

    Type type = assem.GetType(className);   // 註意这里如果使用Type.GetType来取得Type的话,那麼assemblyName指定的类一定要是强命名的

    // 创建无参数实例

    IDAL.IMember member = (IDAL.IMember)type.InvokeMember(className, BindingFlags.CreateInstance, null, null, null);

    Response.Write("创建无参数实例:" + member.ID + "<br/>");

    // 创建有参数实例

    Object[] parameters = new Object[1];

    parameters[0] = 10000;

    IDAL.IMember member1 = (IDAL.IMember)type.InvokeMember(className, BindingFlags.CreateInstance, null, null, parameters);

    Response.Write("创建有参数实例:" + member1.ID + "<br/>");

}

七、动态调用对象方法

Type对象的 InvokeMember方法

MethodInfo对象的Invoke方法

// Type对象的 InvokeMember方法来动态调用方法

private void InvokeMember()

{

    string assemblyName = "SqlModel";

    string className = assemblyName + ".Member";

    string methodName = String.Empty;

    string result = String.Empty;

    Assembly assem = Assembly.Load(assemblyName);

    Object obj = assem.CreateInstance(className);

    Type type = assem.GetType(className);   // 註意这里如果使用Type.GetType来取得Type的话,那麼assemblyName指定的类一定要是强命名的

    // 动态调用无参数的方法

    methodName = "GetName";

    result = (string)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, null);

    Response.Write(methodName + "方法的返回值:" + result + "<br/>");

    // 动态调用有参数的方法

    methodName = "Update";

    Object[] methodParams = new Object[1];

    methodParams[0] = DateTime.Now;

    result = (string)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, methodParams);

    Response.Write(methodName + "方法的返回值:" + result + "<br/>");

    // 动态调用参数构架函数的带有参数的方法

    Object[] parameters = new Object[1];

    parameters[0] = 10000;

    obj = assem.CreateInstance(className,false,BindingFlags.CreateInstance, null, parameters, null, null);

    result = (string)type.InvokeMember(methodName, BindingFlags.InvokeMethod, null, obj, methodParams);

    Response.Write(methodName + "方法的返回值:" + result + "<br/>");

}

// MethodInfo对象的Invoke方法来动态调用方法

private void MethodInfo_Invoke()

{

    string assemblyName = "SqlModel";

    string className = assemblyName + ".Member";

    string methodName = String.Empty;

    string result = String.Empty;

    Assembly assem = Assembly.Load(assemblyName);

    Object obj = assem.CreateInstance(className);

    Type type = assem.GetType(className);   // 註意这里如果使用Type.GetType来取得Type的话,那麼assemblyName指定的类一定要是强命名的

    // 动态调用无参数的方法

    methodName = "GetName";

    MethodInfo methodInfo = type.GetMethod(methodName);

    result = (string)methodInfo.Invoke(obj, null);

    Response.Write(methodName + "方法的返回值:" + result + "<br/>");

    // 动态调用有参数的方法

    methodName = "Update";

    Object[] methodParams = new Object[1];

    methodParams[0] = DateTime.Now;

    MethodInfo method = type.GetMethod(methodName);

    result = (string)method.Invoke(obj, methodParams);

    Response.Write(methodName + "方法的返回值:" + result + "<br/>");

}

--------------------------------------------------------------------------------

以上所使用的SqlModel.Member為:

新建一个SqlModel类库,在其下建立一个Member的类

namespace SqlModel

{

    public class Member : IDAL.IMember

    {

        private int _id = 100;

        public int ID

        {

            get { return _id; }

            set { _id = value; }

        }

        private string _name = "limin";

        public string Name

        {

            get { return _name; }

            set { _name = value; }

        }

        public Member() { }

        public Member(int id)

        {

            _id = id;

        }

        private void Init()

        { }

        public string GetName()

        {

            return _name;

        }

        public string Update (DateTime cdate)

        {

            return "{" + String.Format("ID:{0},Name:{1},CreateDate:{2}",_id,_name,cdate) + "}";

        }

    }

}