C# 反射

实验四:C#反射

具体要求

构建一个components.txt文件,每行代表一个类(比如形状类Shape)的名字(这些类可以来自系统库,或者自己构造);程序逐行扫描该文件,构建对应的类的对象。要求:

  1. 并把这些对象放到数组中;

  2. 列出每个类的字段、方法;

  3. 让用户选择,使得用户可以调用所需要的方法(操作)

  4. 系统随机选择对象(比如形状),随机的执行其操作。从而看系统演化。可能的话,进行界面展示


环境

  1. 操作系统: Windows 10 X64
  2. IDE: visual studio 2017
  3. 语言:C#

步骤一 :Graphic.cs——>Graphic.dll

1.新建一个项目,通过“项目|添加类”命令向其中添加一个Graphic.cs文件,文件包括图形类的声明和定义。文件内容如下。
	using System;
	namespace csharp_exp4
	{
	    public class Rectangle//长方形
	    {
	        public const double PI = Math.PI;
	        protected double x, y;
	        public Rectangle() { }
	        public Rectangle(double x1, double y1)
	        {
	            x = x1;
	            y = y1;
	        }
	        public virtual double Area()//面积
	        {
	            return x * y;
	        }
	        public virtual double Perimeter()//周长
	        {
	            return (x + y) * 2;
	        }
	    }
	    public class Triangle : Rectangle//等腰三角形
	    {
	        public Triangle(double x, double y) : base(x, y)//宽,高
	        { }
	        public override double Area()
	        {
	            return x * y / 2;
	        }
	        public override double Perimeter()
	        {
	            return Math.Sqrt(x * x / 4 + y * y) * 2 + x;
	        }
	    }
	    public class Sphere : Rectangle//圆
	    {
	        public Sphere(double r, double y) : base(r, 0) { }
	        public override double Area()
	        {
	            return PI * x * x;
	        }
	        public override double Perimeter()
	        {
	            return 2 * PI * x;
	        }
	    }
	    public class ellipse : Rectangle//椭圆
	    {
	        public ellipse(double a, double b) : base(a, b) { }
	        public override double Area()
	        {
	            return PI * x * y;
	        }
	        public override double Perimeter()
	        {
	            return 2 * PI * y + 4 * (x - y);
	        }
	    }
	
	}   
2.命令行编译命令(重要)

目的:生成Graphic.dll文件
依次执行以下命令

  • path C:\Windows\Microsoft.NET\Framework\v2.0.50727
  • cd C:\Users\lenovo\source\repos\csharp实验四\csharp实验四
  • csc/target:library Graphic.cs

解释:

  1. 采用命令行方式对C#文件进行编译的程序是csc.exe
  2. 为了能执行csc程序,通过path设置路径,命令格式为“ path + csc.exe的文件夹目录 ” ,一般情况下,其位置是 C:\Windows\Microsoft.NET\Framework\v2.0.50727
  3. cd C:\Users\lenovo\source\repos\csharp实验四\csharp实验四 – 进入存放项目的文件夹
  4. csc/target:library Graphic.cs – 执行CSC程序

结果:
C:\Users\lenovo\source\repos\csharp实验四\csharp实验四路径的文件夹下找到Graphic.dll文件
把Graphic.dll文件 移动到csharp实验四\csharp实验四\bin\Debug目录下。ok了


步骤二 :反射查看成员信息、调用未知类方法(System.Reflection 反射命名空间)

知识点1—Assembly类

加载程序集

Assembly assembly = Assembly.LoadFrom("Graphic.dll");//加载程序集(cs文件生成.dll文件,.dll文件是一个程序集)
Console.WriteLine("name of assembley:"+assembly.GetName());//输出程序集的Name

根据类名创建类型的一个实例

 object myobj =assembly.CreateInstance(nsp+classname,true, BindingFlags.Default, null, ars, null, null);
知识点2—Type类(获得实例对象的成员信息)
  Type mytype = myobj.GetType();
  if (myobj!=null)
    Console.WriteLine("<{0}>类名:{1}",classList.Count,mytype.Name);
            
  MethodInfo[] ms = mytype.GetMethods();
    Console.WriteLine("  {0}的方法个数:{1}", mytype.FullName, ms.Length);
  for (int i=0;i<ms.Length;i++)
    Console.WriteLine("  ({0}){1}", i+1,ms[i].Name);

  FieldInfo[] fs = mytype.GetFields();
  Console.WriteLine("  {0}的字段个数:{1}", mytype.FullName, fs.Length);
  for (int i = 0; i < fs.Length; i++)
  Console.WriteLine("  ({0}){1}", i+1, fs[i].Name);
知识点3—调用方法

[方法名].Invoke([实例对象], [实参])

知识点4—读取文件
  //读取文件
        string path = "exp5_sharp.txt";
        FileStream f = File.OpenRead(path);
        StreamReader sr = new StreamReader(f, Encoding.Default);
        f.Seek(0, SeekOrigin.Begin);    
        while (sr.Peek() > -1)//当文件指针。。
        {
            classname = sr.ReadLine();//类名
            ...
        }

具体代码

    static void Main(string[] args)
    {
        Assembly assembly = Assembly.LoadFrom("Graphic.dll");//加载程序集(cs文件生成.dll文件,.dll文件是一个程序集)
        Console.WriteLine("name of assembley:"+assembly.GetName());//输出程序集的Name
        Type[] types = assembly.GetTypes();
        
        //读取文件
        string path = "exp5_sharp.txt";
        FileStream f = File.OpenRead(path);
        StreamReader sr = new StreamReader(f, Encoding.Default);
        f.Seek(0, SeekOrigin.Begin);
        //对象放到数组中;列出每个类的字段、方法;
        string classname;
        string nsp = "csharp_exp4.";
        ArrayList classList = new ArrayList();
        while (sr.Peek() > -1)//当文件指针。。
        {
            classname = sr.ReadLine();//类名
            object[] ars = { 3,4};//参数
           

            object myobj =assembly.CreateInstance(nsp+classname,true, BindingFlags.Default, null, ars, null, null);
            //加入数组
            classList.Add(myobj);

            Type mytype = myobj.GetType();
            if (myobj!=null)
                Console.WriteLine("<{0}>类名:{1}",classList.Count,mytype.Name);
            
            MethodInfo[] ms = mytype.GetMethods();
                Console.WriteLine("  {0}的方法个数:{1}", mytype.FullName, ms.Length);
            for (int i=0;i<ms.Length;i++)
                Console.WriteLine("  ({0}){1}", i+1,ms[i].Name);

            FieldInfo[] fs = mytype.GetFields();
            Console.WriteLine("  {0}的字段个数:{1}", mytype.FullName, fs.Length);
            for (int i = 0; i < fs.Length; i++)
                Console.WriteLine("  ({0}){1}", i+1, fs[i].Name);

        }

        Console.Write("-----------------------\n1系统操作,2选择操作:");
        string kase = Console.ReadLine();
        switch (kase)
        {
            case "1":
                TimeSpan ts =new DateTime() - new DateTime(1970, 1, 1);
                float hm = ts.Milliseconds;
                Random myrandom = new Random();
                int classNum = myrandom.Next(0, 3);
                object myobject = classList[classNum];//随机选择一个类


                int funNum;
                while (true)
                {
                    funNum = myrandom.Next(1, 6);
                    if (funNum != 4)
                        break;
                }          
                Type type = classList[classNum].GetType();
                MethodInfo[] md = type.GetMethods();
                Console.WriteLine( type.Name+"——" +md[funNum - 1].Name+":" + md[funNum - 1].Invoke(myobject, null)+ "\n-----------------------");
                break;



            case "2":
                while (true)
                {
                    //3)让用户选择,使得用户可以调用所需要的方法(操作)
                    Console.Write("请选择类对象<1-4>或退出0:");
                    int cur_class = int.Parse(Console.ReadLine());

                    if (cur_class == 0)
                        break;
                    if(cur_class<0||cur_class>4)
                    {
                        Console.WriteLine("输入错误!\n-----------------------");
                        continue;
                    }
                    Type curtype = classList[cur_class - 1].GetType();
                    MethodInfo[] mds = curtype.GetMethods();
                    Console.WriteLine("  {0}的方法个数:{1}", curtype.FullName, mds.Length);
                    for (int i = 0; i < mds.Length; i++)
                        Console.WriteLine("  ({0}){1}", i + 1, mds[i].Name);
                    Console.Write("请选择方法(except 4):");
                    int cur_fun = int.Parse(Console.ReadLine());
                    object myshape = classList[cur_class - 1];
                    if (cur_fun < 1 || cur_fun > 6||cur_fun==4)
                        Console.WriteLine("输入错误!\n-----------------------");
                    else
                        Console.WriteLine(myshape.GetType().Name + "——" + mds[cur_fun - 1].Name + ":" + mds[cur_fun - 1].Invoke(myshape, null)+ "\n-----------------------" +
                            "");                                                  
                }
                break;
        }

        Console.ReadKey();
    }

截图展示

1.类的信息

2.用户选择,调用需要的方法

3.系统随机选择对象(比如形状),随机的执行其操作。

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值