步步为营-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 完善*和/

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

posted @ 2017-04-23 20:05  逍遥小天狼  阅读(206)  评论(0编辑  收藏  举报