zoukankan      html  css  js  c++  java
  • 反射,插件示例

    反射:

    反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改其本身状态或行为的一种能力。

    不需要走过去看前面是否有阻挡物,只需要利用声波的反射,就可以知道前面是否有阻挡,和阻挡物有多远。

    在程序中也是如此,现实中利用声波,导致我们可以不用实际走过去,而程序中利用 类的自我描述信息。导致我们不需要一个实际的对象,只要告诉我类的命名空间和类名,或者java的包名和类名。就可以知道类的方法属性,甚至建立一个实例出来,或修改类属性。

    一定要清晰认识到,由于提出了程序应该有访问,检测,修改自己状态和行为的能力的概念,所以才有了反射技术的概念。所以反射一般必须满足它设计的2个初衷,1.自我描述,2自我修改。

    c#的定义

    反射:一个运行的程序查看本身的元数据或其他程序的元数据的行为。

    java反射的一般定义

    JAVA反射机制是在运行状态中,

    1.对于任意一个类,都能够知道这个类的所有属性和方法;

    2.对于任意一个对象,都能够调用它的任意方法和属性;

    这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制

     它是现代框架的灵魂,几尽所有的框架能够提供的一些自动化机制都是靠反射实现的,这也是为什么基础框架都不允许你覆盖掉默认的无参构造器的原因,因为框架需要以反射机制利用无参构造器创建实例。

    c# 的插件例子:

    子游戏 ,编译为 一个 一个 的  dll. 而 游戏 管理 中心 。就是界面 程序 。可以 加载 任何游戏 插件 ,只要 实现 了 子游戏 接口。

    原来 看  c++ 写的 比较 复杂 。在c#中 真的是 非常 简便了 。超级简单。

    游戏管理中心 。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Reflection;
    
    namespace helloworld
    {
        public interface  Game_Interface
        {
             string GameName();
             void Start();
             void End();
        }
    
    
        public class GameCenter
        {
            List<Game_Interface> Games;
            public GameCenter()
            {
                Games = new List<Game_Interface>();
            }
    
            public void StartGames()
            {
                //模拟从xml配置文档,读出了游戏名字。
                //string game1name = getnameFormxml();
                List<string> gamenames=new List<string>();
                gamenames.Add("Game_land");
                gamenames.Add("Game_machong");
    
                foreach(string gamename in gamenames)
                {
                    Assembly tempAss = Assembly.Load(gamename);//根据程序集名字装载程序集.xxx.dll
    
                    Type temptype = null;
                   // object obj = CreateInstance1(tempAss, "subgame." + gamename, out temptype);//一般2种方法得到一个类的实例和类型信息.  1通过指定命名空间加类名 xxx.xxx
                    object obj = CreateInstance2(tempAss, typeof(Game_Interface),out temptype);//2.通过查看某些属性。如这里是查看是否有实现了某个接口的类。
    
    
                    MethodInfo m1 = temptype.GetMethod("Start");//调用方法可以有2种方式  1.继续反射。从对象中。手工调用某个方法。
                    m1.Invoke(obj, null);
    
    
                    Game_Interface tempGame = obj as Game_Interface;//2.如果是实现了某个接口.那么可以转为接口类型.一般采用这种,强类型肯定比手工写方法名字 更安全。
                    if(tempGame!=null)
                    {
                        tempGame.Start();
                    }
                }
            }
    
            object CreateInstance1(Assembly tempAss, string typename,out Type mytype)
            {
                Type temptype = tempAss.GetType(typename);//"subgame." + gamename
                object obj = Activator.CreateInstance(temptype);//从程序集中,根据命名空间和类名组成的全地址,实力化一个对象出来。
                mytype = temptype;
                return obj;
            }
    
            object CreateInstance2(Assembly tempAss, Type interfacetype, out Type mytype)
            {
                Type[] alltypes = tempAss.GetTypes();
                Type wantType = null;
                for (int i = 0; i < alltypes.Length;i++ )
                {
                    Type itype= alltypes[i].GetInterface("Game_Interface");//看看有没有接口类型。返回的只是接口类型而已。
                    if (itype != null)
                    {
                        wantType = alltypes[i];//这个才是实现了接口的类型。
                        break;
                    }
                }
                if (wantType != null)
                {
                    object obj = Activator.CreateInstance(wantType);
                    mytype = wantType;
                    return obj;
                }
                else
                {
                    mytype = null;
                    return null;
                }
            }
    
    
    
            public void StopGame(int gameIndex)
            {
    
            }
    
            public void CreatRound(int gameIndex)
            {
    
            }
    
        }
    }

    子 游戏 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace subgame
    {
        public class Game_machong:helloworld.Game_Interface
        {
            public string gamename = "machong";
    
            public string GameName()
            {
                return gamename;
            }
    
            public void Start()
            {
                Console.WriteLine("Start machong");
            }
    
            public void End()
            {
                Console.WriteLine("End machong");
            }
        }
    }

    子游戏 

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace subgame
    {
        public class Game_land:helloworld.Game_Interface
        {
            public string gamename = "land";
            public string GameName()
            {
                return gamename;
            }
    
            public void Start()
            {
                Console.WriteLine("Start land");
            }
    
            public void End()
            {
                Console.WriteLine("End land");
            }
        }
    }

    java 的例子

    //反射:测试运行时创建类,修改私有变量为外部可以访问。
        //一定要清晰,由于提出了程序应该有访问,检测,修改自己状态和行为的能力的概念,所以才有了反射技术的概念。
        //所以反射一般必须满足它设计的2个初衷,1.自我描述,2自我修改。
        private void Myreflect()
        {
            MyBook cpp=new MyBook(4, 1, "c++");
            LSLog.Log_INFO(cpp.getInfo());
    
            try
            {
                //1.running time create obj   这就是反射的初衷1:自我描述,不需要编译时,运行时都可以建立一个对象,所以为插件机制提供了简便的方式。
                Class BookReflect= Class.forName("com.linson.android.hiandroid2.JavaPractice.MyBook");
                MyBook javabook= (MyBook) BookReflect.getConstructor().newInstance();
                //2.set value to private field. 这就是反射的初衷2:自我修改,可以把私有字段设置为可以访问。为某些特殊情况提供了可能。当然也是双刃剑,可以自我修改,就违背了当初类设计的初衷。
                Field  privateField=BookReflect.getDeclaredField("price");
                privateField.setAccessible(true);//这里的自我修改,满足了反射必须有自我修改的能力的规范。
                privateField.set(javabook, 8);
                Field fname=BookReflect.getField("name");
                fname.set(javabook, "java");
                LSLog.Log_INFO(javabook.getInfo());
            }
            catch (Exception e)
            {
                LSLog.Log_Exception(e);
            }

    c# 例子

    “反射”其实就是利用程序集的元数据信息。 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间。
    
    1、假设你要反射一个 DLL 中的类,并且没有引用它(即未知的类型): 
    Assembly assembly = Assembly.LoadFile("程序集路径,不能是相对路径"); // 加载程序集(EXE 或 DLL) 
    dynamic obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)"); // 创建类的实例 
    
    2、若要反射当前项目中的类(即当前项目已经引用它了)可以为:
    
    Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集 
    dynamic obj = assembly.CreateInstance("类的完全限定名(即包括命名空间)"); // 创建类的实例,返回为 object 类型,需要强制类型转换
    
    3、也可以为:
    
    Type type = Type.GetType("类的完全限定名"); 
    dynamic obj = type.Assembly.CreateInstance(type); 
    
    4、不同程序集的话,则要装载调用,代码如下:
    System.Reflection.Assembly.Load("程序集名称(不含文件后缀名)").CreateInstance("命名空间.类名", false);
    如:
    dynamic o = System.Reflection.Assembly.Load("MyDll").CreateInstance("MyNameSpace.A", false);
    
    5、根据对象实例创建该对象所属类的新对象
    Type type = protocol.GetType(); //获取protocol类型
    
    Assembly assembly = Assembly.GetExecutingAssembly(); // 获取当前程序集
    
    string name = type.FullName;
    
    IProtocol obj = (IProtocol)assembly.CreateInstance(name); //根据类名获得新对象
    
    注意:由于要用到dynamic ,需要把target 改为4.0 ,如果编译时出现“找不到编译动态表达式所需的一个或多个类型。是否缺少引用?”的错误,是因为缺少一个引用,在项目里引用Miscorsoft.CSharp类库,添加后就能编译成功。
  • 相关阅读:
    02.02.03第3章 餐饮项目案例(Power BI商业智能分析)
    02.02.02 第2章 制作power bi图表(Power BI商业智能分析)
    MySQL 目录结构信息
    Commons-FileUpload 文件上传(模板)
    Commons-FileUpload 常用API
    Java DOM方式解析XML(模板)
    常用的节点类型
    MySQL权限及登陆、退出方法
    Java 锁
    线程的状态
  • 原文地址:https://www.cnblogs.com/lsfv/p/9607826.html
Copyright © 2011-2022 走看看