• 【转载】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) + "}";
    }
    }
    }

  • 相关阅读:
    sun.misc.BASE64Encoder----》找不到jar包的解决方法
    javax.validation.UnexpectedTypeException: HV000030: No validator could be found for constraint-实体报错
    避免MQ消息重发的简单实现思路
    使用Spring的@Scheduled实现定时任务参数详解
    重置密码解决MySQL for Linux错误 ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
    安装mysql zip5.7版--安裝
    bzoj3983
    bzoj4044
    bzoj1064
    bzoj4042
  • 原文地址:https://www.cnblogs.com/icebutterfly/p/7677550.html
Copyright © 2020-2023  润新知