• 步步为营-32-反射实例-计算器


    说明:设计模式-简单工厂(参考步步为营-09随笔),反射

    1 添加窗体应用程序,做好UI界面.这里不添加按钮,按钮通过文档自动创建

    2 添加用于运算的父类,但是为了实现反射,需要将其放在类库中,故先加类库ProOperation,

      2.1 分析父类,

        首先定义成公共抽象类,方便子类实现,

        需要两个属性(FirstNumber和SecondNumber),

        还需要一个属性运算符Operator,只需要get方法

        需要一个方法获得结果GetResult和一个含有两个参数的构造方法  

      
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace ProOperation
    {
      public abstract  class Operation
        {
          public Operation(double number1, double number2) 
          {
              this.FirstNumber = number1;
              this.SecondNumber = number2;
          }
          public  double FirstNumber { get; set; }
          public  double SecondNumber { get; set; }
    
            public abstract string Operator { get;  }
    
            public abstract double GetResult();
           
        }
    }
    Operation


    3 同理子类ProAdd类库和Add子类

      3.1 添加引用导入命名空间using ProOperation;  

      
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using ProOperation;
    
    namespace ProAdd
    {
       public class Add:Operation
        {
           public Add(double a, double b) : base(a,b) { }
     
    
            public override string Operator
            {
                get
                {
                    return "+";
                }
               
            }
    
            public override double GetResult()
            {
                return this.FirstNumber + this.SecondNumber;
            }
        }
    }
    Add

      3.2 在窗体应用程序的bin/debug目录下,添加Plug文件夹,需要将ProAdd.dll文件复制到该文件下

    4 创建工厂类
      4.1 添加引用导入命名空间using ProOperation;using System.Reflection;using System.IO;  

      
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using ProOperation;
    using System.Reflection;
    using System.IO;
    namespace ProFactory
    {
       public class Factory
        {
           public static Operation GetOper(string  operType,double n1,double n2) 
           {
               Operation oper = null;
               //01-动态获取程序集
    
               //01-a 获取程序集的目录
               string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plug");//此时Plug目录中有很多类型的文件如.dll,.xml等
              
               //01-b ,所以进一步筛选===获得所有程序集文件的全路径
               String[] files = Directory.GetFiles(path, "*.dll");//此时 数组中可能包含{Add.dll,Sub,dll,Mul.dll}等
               
    
               //02-加载程序集
               foreach (var item in files)
               {
                   //02-a-加载程序集
                   Assembly ass = Assembly.LoadFile(item);//此时假设是Add.dll 其中可能包含多个类{A.cs,Add.cs,B.cs}等
    
                   //02-b ,所以进一步筛选===获得所有程序集文件中的类文件
                   Type[] types = ass.GetExportedTypes();
                   foreach (var dllType in types)
                   {
                       //判断当前对象是否符合要求
                       if (dllType.IsSubclassOf(typeof(Operation))&&!dllType.IsAbstract)
                       {
                           //03-a-创建子类对象,交给父类对象
                           oper = (Operation)Activator.CreateInstance(dllType, n1, n2);//此时假设是Add.dll 其中可能是{A.cs,Add.cs,B.cs}创建的对象
    
                           //03-b-对创建的子类对象进一步筛选
                           if (operType == oper.Operator)//operType 是传入的字符串"+,-,*,/" 而oper.Operator是类Operation中的运算符属性
                           {
                               return oper;
                           }
                       }
                   }
    
               }
    
               return oper;
           }
        }
    }
    Factory

    5 回过头来完善窗体应用程序

      5.1 在bin/debug目录下添加文本文件Config.txt,文件内容如下

      5.2 添加引用using ProOperation;using ProFactory;

      5.3 代码  

      
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using ProOperation;
    using ProFactory;
    
    namespace ProCalculator
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                //1 首先读取配置文件
                string[] lines = File.ReadAllLines("Config.txt");
    
                //2 自动创建按钮
                //2-a设置按钮初始位置
                int x = 100;
                int y = 222;
                foreach (string item in lines)
                {
                    //2-b 遍历结合创建按钮
                    Button btn = new Button();
                    btn.Location = new Point(x,y);
                    x =x + 80;
                    btn.Text = item;
    
                    btn.Click += btn_Click;//添加事件
                    this.Controls.Add(btn);//添加到窗体上
                }
            }
    
            private void btn_Click(object sender, EventArgs e)
            {
                Button btn = sender as Button;
                double n1 ,n2;
                if (double.TryParse(txtNumber1.Text, out n1) && double.TryParse(txtNumber2.Text, out n2))
                {
                    //获得简单工厂类提供的父类对象
                    Operation oper = Factory.GetOper(btn.Text,n1,n2);
                    lblResult.Text = oper.GetResult().ToString();
                } 
    
            }
        }
    }
    View Code

    6 完善*和/

    完整代码在对应的百度网盘目录下

  • 相关阅读:
    this指向问题
    原生js实现的金山打字小游戏(实例代码详解)
    js实现点赞效果
    .net core部署到linux可能碰到的问题
    Linux curl命令详解 Web程序
    用十年来学编程
    JAVA的字符串拼接与性能
    PHP学习的技巧和学习的要素总结
    php实现验证邮箱格式的代码实例
    PHP页面中文乱码处理办法
  • 原文地址:https://www.cnblogs.com/YK2012/p/6753732.html
Copyright © 2020-2023  润新知