首页 > 编程语言 >C# 反射

C# 反射

时间:2023-08-28 10:44:09浏览次数:30  
标签:反射 assembly Assembly C# 创建对象 tItem Type

​反射是一种动态分析程序集、模块、类型、字段等目标对象的机制,它的实现依托于元数据。元数据是存储在PE 文件中的数据块,它详细记录了程序集或模块内部的结构、引用的类型和程序集和清单

一、加载dll,读取相关信息

            //加载程序集
            Assembly assembly = Assembly.Load("kzttest");

            //获取程序集中所有的类
            Type[] type = assembly.GetTypes();

            //获取程序集中特定类
            Type tItem = assembly.GetType("kzttest.Generics");

            //获取特定类中的所有构造函数
            ConstructorInfo[] cInfor = tItem.GetConstructors();
            //函数实现
            cInfor[0].Invoke(null);

            //获取特定类中的所有属性
            PropertyInfo[] cOutfor = tItem.GetProperties();
            for (int i = 0; i < cOutfor.Length; i++)
            {
                Console.WriteLine($"name:{cOutfor[i].Name},type:{cOutfor[i].PropertyType.FullName}");
            }

            //获取特定类中的所有方法
            MethodInfo[] methordInfo = tItem.GetMethods();

            //获取特定类中的所有接口
            Type[] typeInter = tItem.GetInterfaces();

二、反射创建对象

1、通过Activator.CreateInstance()方法来创建对象2、反射创建对象的代码
//1.加载程序集
Assembly assembly = Assembly.Load("DB.SQLServer");
//2.获取程序集中的特定类
Type tItem = assembly.GetType("DB.SQLServer.ReflectionTest");
 //3.1 无参构造函数
Activator.CreateInstance(tItem);
 //3.2 一个参数的构造函数
Activator.CreateInstance(tItem ,"1");
//3.3 两个参数的构造函数
 Activator.CreateInstance(tItem , 1,"2");
3、反射破坏单例,调用私有构造函数单例代码
public sealed class Singleton
    {
        private Singleton()
        {
            Console.WriteLine("初始化一次");
        }

        private static Singleton Instance = new Singleton();

        public static Singleton CreateInstance()
        {
            return Instance;
        }
    }
破坏单例,调用私有构造函数代码
            //加载程序集
            Assembly assembly = Assembly.Load("kzttest");

            //获取程序集中特定类
            Type tItem = assembly.GetType("kzttest.Singleton");

            //创建对象
            Activator.CreateInstance(tItem, true);

三、IOC(反射+简单工厂+配置文件)

通过XML动态创建对象注:传统创建对象、接口创建对象和直接反射创建对象   都已经发布 生成dll,无法动态修改配置文件:
<appSettings>
    <!--直接修改配置文件,可以修改数据库连接牛逼,可以直接切换 oracle 、mysql数据库,发布后可以直接通过改配置文件,切换数据库,代码什么也不用改,体会:反射+面向接口编程-->
    <!--前提:相应的DBHelper类必须满足接口约束,需要把Oracle或MySql的dll文件拷贝到Reflection中的bin文件中  -->
    <!--SQLServer改为:         -->
    <!--<add key="IDBHelper-dllName" value="DB.SQLServer"/>
    <add key="IDBHelper-className" value="DB.SQLServer.DBHelper"/>-->
    <!--Oracle改为:         -->
    <!--<add key="IDBHelper-dllName" value="DB.Oracle"/>
    <add key="IDBHelper-className" value="DB.Oracle.DBHelper"/>-->
    <!--MySql改为:         -->
    <add key="IDBHelper-dllName" value="DB.MySql"/>
    <add key="IDBHelper-className" value="DB.MySql.DBHelper"/>
  </appSettings>
简单工厂:
/// <summary>
    /// 简单工厂,创建对象
    /// </summary>
    public class SimpleFactory
    {
        private static string IDBHelperdllName = ConfigurationManager.AppSettings["IDBHelper-dllName"];
        private static string IDBHelperClassName = ConfigurationManager.AppSettings["IDBHelper-className"];

        public static IDBHelper CreateDBHelper()
        {
            Assembly assembly = Assembly.Load(IDBHelperdllName);
            Type type = assembly.GetType(IDBHelperClassName);
            object obj = Activator.CreateInstance(type);
            return (IDBHelper)obj;
        }

    }
调用:
Console.WriteLine("------------------------------------4. IOC(反射+简单工厂+配置文件)--------------------------------------");
//4. IOC(反射+简单工厂+配置文件)(不需要直接添加对其引用,只需要把相应的程序生成路径改成Reflection中即可)
IDBHelper idb3 = SimpleFactory.CreateDBHelper();
idb3.Query();

四、反射调用

            //加载程序集
            Assembly assembly = Assembly.Load("kzttest");

            //获取程序集中特定类
            Type tItem = assembly.GetType("kzttest.Generics");

            //创建对象
            object obj = Activator.CreateInstance(tItem);


            Console.WriteLine("---------------------------------2.1 调用无参、有参的实例方法-------------------------------------");
            //获取指定方法 只能一对一 不可重载  后面通过参数实现
            MethodInfo methord = tItem.GetMethod("Say2");
            //调用 无参
            methord.Invoke(obj, null);

            //获取指定方法 只能一对一 不可多态
            MethodInfo methord3 = tItem.GetMethod("Say3");
            //调用 有参
            methord3.Invoke(obj, new object[] { "有参啊" });

            Console.WriteLine("---------------------------------2.3 调用重载方法(需要在创建方法的时候,把类型传进去)-------------------------------------");
            //调用重载方法  需要在创建方法的时候,把类型传进去
            MethodInfo methord4 = tItem.GetMethod("Do", new Type[] { });
            methord4.Invoke(obj, null);

            MethodInfo methord5 = tItem.GetMethod("Do", new Type[] { typeof(string) });
            methord5.Invoke(obj, new object[] { "11" });

五、好处、局限

1、反射的好处:
  • 反射是.NET中的重要机制,通过反射,可以在运行时获得程序或程序集中每一个类型(包括类、结构、委托、接口和枚举等)的成员和成员的信息。
  • 有了反射,即可对每一个类型了如指掌。另外我还可以直接创建对象,即使这个对象的类型在编译时还不知道。
2、局限性能没有直接创建对象好

标签:反射,assembly,Assembly,C#,创建对象,tItem,Type
From: https://www.cnblogs.com/buzheng11/p/17661656.html

相关文章

  • Spring3中替换默认拦截器的方法BeanFactoryPostProcessor
    由于Spring默认的静态资源处理器不能满足需求,需要做一些自己的处理,但mvc:resources的标签又挺好用的,不想每次配置静态资源目录的时候,还要特殊指定处理器,也不想修改任何配置代码,于是找到了使用BeanFactoryPostProcessor的方法 实现代码如下:importorg.springframework.beans.Beans......
  • 在spring、tomcat中使用多数据源并支持分布式事务管理
    题目起得有点模糊,第一次接触这东西,还不怎么理解。 起因: 小项目,没有用分布式,但要操作两个数据库。本以为随便用spring配置两个数据源就搞定,查询是没问题,问题是有一个数据库老是插不进数据。Google狂搜之后,大概了解到是事务控制的问题。我用的是spring的声明式事务管理(<tx:annotat......
  • 如何把Https网站中的安全证书导入到java中的cacerts证书库中?
     如何把Https网站中的安全证书导入到java中的cacerts证书库中?在项目开发中,有时会遇到与SSL安全证书导入打交道的,如何把证书导入java中的cacerts证书库呢?其实很简单,方法如下:每一步:进入某个https://www.xxx.com开头的网站,把要导入的证书下载过来,在该网页上右键>>属性......
  • 完美配置Tomcat的HTTPS
    Tomcat配置HTTPS的文章到处都有,过程也比较简单,随后文中会转一段过来。但对于启用APR情况下报异常“java.lang.Exception:ConnectorattributeSSLCertificateFilemustbedefinedwhen usingSSLwithAPR”的解决方法上处理的都比较偷懒,通常都是把APR注释掉不启用APR。做为一......
  • SpringMVC3的ResponseBody返回字符串乱码问题解决
    SpringMVC的@ResponseBody注解可以将请求方法返回的对象直接转换成JSON对象,但是当返回值是String的时候,中文会乱码 原因是因为其中字符串转换和对象转换用的是两个转换器,而String的转换器中固定了转换编码为"ISO-8859-1" 网上也很多种解决方法,有通过配置Bean编码的,也有自己重写转......
  • Maven plugin中的lifecycle、phase、goal、mojo概念及作用的理解
       首先,说些题外话,maven的plugin真的很容易写,很多时候,我们只是被plugin这个词吓倒了,总以为插件这玩意,是专家才能写的,我maven都没精通,怎么写得出自己的plugin呢,其实不然,起码在maven中,写一个自己的plugin还是非常简单的,其它软件的插件,要看情况,有些的确是要天才级人物才写得出,......
  • CSS的htc文件对于脚本生成的html无效的处理方法
    最近用PIE.htc开发CSS3的网页时,发现用到PIE.htc的CSS效果对于用脚本生成的html代码都无效的情况众所周知htc是IE针对CSS开放的一种特殊实现方式htc的实现是在页面载入完成后开始的,类似于js的window.onload(),它并不是像CSS语言那样,成为浏览器原生的语言,所以当页面内容使用js生成时,其......
  • 在SpringBoot中使用WebSocket
    一、概述最近在SpringBoot中用到了WebSocket的功能,在此记录一下使用步骤。SpringBoot使用WebSocket还是比较简单的,只需要4步就行了。如下二、使用步骤第一步:在pom.xml文件中导入坐标<!--websocketdependency--><dependency><grou......
  • 在CXF中用JAXB数据绑定支持Map类型
     一些java类型不能自然映射成xml,例如,HashMap或其他非JavaBean类,这个时候可以覆盖XmlAdapter来自定义转换方法。XMlAdapter讲解: javax.xml.bind.annotation.adapters 类XmlAdapter<ValueType,BoundType> 类型参数:BoundType-JAXB不知道如何处理的一些类型。编写一个适配......
  • HarmonyOS/OpenHarmony(Stage模型)卡片开发应用上下文Context使用场景二
    3.创建其他应用或其他Module的Context基类Context提供创建其他应用或其他Module的Context的方法为createModuleContext(moduleName:string),创建其他应用或者其他Module的Context,从而通过该Context获取相应的资源信息(例如获取其他Module的获取应用开发路径信息)。调用createModuleCon......