计算器插件开发
1、Calculator.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Calculator_DLL
{
//用来明确所有插件开发人员的开发规范
public abstract class Calculator
{
public int NumberOne { get;set; }
public int NumberTwo { get;set; }
public abstract string Oper { get; }//抽象属性
public Calculator(int n1,int n2)
{
this.NumberOne = n1;
this.NumberTwo = n2;
}
//提供一个计算的方法,具体的计算公式,留给插件开发人员
public abstract int GetResult();
}
}
2、Calculator_Add.cs
using Calculator_DLL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Calculator_DLL_Add
{
public class Calculator_Add : Calculator
{
public Calculator_Add(int n1, int n2) : base(n1, n2)
{
}
public override string Oper { get { return "+"; } }
public override int GetResult()
{
return this.NumberOne + this.NumberTwo;
}
}
}
3、Calculator_Sub.cs
using Calculator_DLL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Calculator_DLL_Sub
{
public class Calculator_Sub : Calculator
{
public Calculator_Sub(int n1, int n2) : base(n1, n2)
{
}
public override string Oper { get { return "-"; } }
public override int GetResult()
{
return this.NumberOne-this.NumberTwo;
}
}
}
4、Calculator_Factory.cs
using Calculator_DLL;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Calculator_Factory_DLL
{
/// <summary>
/// 计算器插件的工厂,根据用户的选择,返回对应的计算对象(插件对象)
/// </summary>
public class Calculator_Factory
{
/// <summary>
/// 根据用户选择的操作符,创建对应的插件对象(是用父类屏蔽了所有子类插件对象)
/// </summary>
/// <param name="oper">用户选择的操作符</param>
/// <param name="n1">数字1</param>
/// <param name="n2">数字2</param>
/// <returns>对应的计算插件对象</returns>
public static Calculator GetCalculator(string oper,int n1,int n2)
{
Calculator cal = null;
//Assembly:表示程序集 GetExecutingAssembly():获取包含当前执行的代码的程序集 Location:位置,也就是路径
string path = Assembly.GetExecutingAssembly().Location;
//GetDirectoryName():返回指定路径字符串的目录信息
path = Path.GetDirectoryName(path);//DLL程序集的上一个目录,也就是Debug目录
path = Path.Combine(path, "Plug-in-Components");
//读取文件夹下的所有插件(Add、Sub)
string[] files = Directory.GetFiles(path);
//遍历所有类库文件,从里面找到我们规范的类型(类型要求:继承了Calculator,并且重写了其中的抽象成员,并且不是抽象的)
foreach (var file in files)
{
//LoadFile():加载指定路径上的程序集文件的内容
Assembly ass = Assembly.LoadFile(file);
//GetExportedTypes():获取程序集中定义的公共类型
Type[] types = ass.GetExportedTypes();
//判断类型是否为我们需要的类型
foreach (var type in types)
{
//开始筛选
//IsAssignableFrom():确定指定类型的实例是否能分配给当前实例(看有没有继承关系)
//IsAbstract:判断当前类型是否是抽象的
if (typeof(Calculator).IsAssignableFrom(type)&&!type.IsAbstract)
{
//创建type的对象
object o =Activator.CreateInstance(type,n1,n2);
cal = o as Calculator;
//如果计算对象的Oper属性==用户传入的Oper值
if (cal.Oper==oper)
{
return cal;
}
}
}
}
return cal;
}
}
}
5、Form1.cs
using Calculator_DLL;
using Calculator_Factory_DLL;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 插件记事本
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//1、读取配置文件,创建对应的按钮对象
string path = Assembly.GetExecutingAssembly().Location;
path=Path.GetDirectoryName(path);
path = Path.Combine(path, "CalculatorConfig.txt");
//2、读取配置文件
string[] operLines = File.ReadAllLines(path);
int x = 100;
//3、创建按钮对象
for (int i = 0; i < operLines.Length; i++)
{
Button btn = new Button();
btn.Text = operLines[i];
btn.Size = new Size(75, 23);
btn.Location = new Point(326 + i * x, 257);
btn.Click += Btn_Click;
this.Controls.Add(btn);
}
}
private void Btn_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
string oper = btn.Text;
Calculator cal = Calculator_Factory.GetCalculator(oper,int.Parse(txtNumberOne.Text),int.Parse(txtNumberTwo.Text));
if (cal != null)
{
lblResult.Text = cal.GetResult().ToString();
}
}
}
}
事件
概念:事件,就是一个类型安全的委托(事件是安全的,因为在类的外部,事件只能被赋值,而不能被调用)
事件的三个重要组成部分:注册事件、触发事件、响应事件
递归
概念:在方法中,自己调用自己。必须在满足某个条件的时候,退出递归
递归查找所有的文件夹和文件
private void Form1_Load(object sender, EventArgs e)
{
//递归加载指定目录下,所有的文件夹和文件
string path = @"C:\Windows\Microsoft.NET\Framework64\v4.0.30319";
LoadData(path, treeView2.Nodes);
}
private void LoadData(string path, TreeNodeCollection nodes)
{
//1、获取该路径下所有的文件夹
string[] dirs = Directory.GetDirectories(path);
//1.1 把所有的子目录的路径,添加到Treeview上
foreach (var item in dirs)
{
//tn就是根节点
TreeNode tn = nodes.Add(Path.GetFileName(item));
LoadData(item, tn.Nodes);
}
//2、获取该路径下所有的文件
string[] files = Directory.GetFiles(path);
foreach (var item in files)
{
nodes.Add(Path.GetFileName(item));
}
}
XML
XML:可扩展的标记语言
通过代码创建XML文档
internal class Program
{
static void Main(string[] args)
{
//1、在内存中,创建XML文档对象
XmlDocument xml = new XmlDocument();
//2、创建文档声明
XmlDeclaration dec = xml.CreateXmlDeclaration("1.0", "utf-8", null);
//2.1 把创建的文档声明,添加到xml文档中
xml.AppendChild(dec);
//3、创建根节点
XmlElement books = xml.CreateElement("Books");
//3.1 把创建的根节点,添加到xml文档中
xml.AppendChild(books);
//4.1、给根节点,添加对应的属性
XmlElement book1 = xml.CreateElement("Book");
//Attribute :特性 [Serilizeble] Property:属性
XmlAttribute book1_id = xml.CreateAttribute("ID");
//给属性赋值
book1_id.Value = "00001";
//把属性跟Book标签绑定到一起
book1.Attributes.Append(book1_id);
books.AppendChild(book1);
//4.2 给根节点,添加对应的子节点
XmlElement book1_name = xml.CreateElement("Name");
//给子节点赋值
book1_name.InnerText = "金瓶梅";
book1.AppendChild(book1_name);
//4.2 给根节点,添加对应的子节点
XmlElement book1_author = xml.CreateElement("Author");
//给子节点赋值
book1_author.InnerText = "西门大官人";
book1.AppendChild(book1_author);
//4.2 给根节点,添加对应的子节点
XmlElement book1_price = xml.CreateElement("Price");
//给子节点赋值
book1_price.InnerText = "10";
book1.AppendChild(book1_price);
//4.1、给根节点,添加对应的属性
XmlElement book2 = xml.CreateElement("Book");
//Attribute :特性 [Serilizeble] Property:属性
XmlAttribute book2_id = xml.CreateAttribute("ID");
//给属性赋值
book2_id.Value = "00002";
//把属性跟Book标签绑定到一起
book2.Attributes.Append(book2_id);
books.AppendChild(book2);
//4.2 给根节点,添加对应的子节点
XmlElement book2_name = xml.CreateElement("Name");
//给子节点赋值
book2_name.InnerText = "水浒传";
book2.AppendChild(book2_name);
//4.2 给根节点,添加对应的子节点
XmlElement book2_author = xml.CreateElement("Author");
//给子节点赋值
book2_author.InnerText = "潘金莲";
book2.AppendChild(book2_author);
//4.2 给根节点,添加对应的子节点
XmlElement book2_price = xml.CreateElement("Price");
//给子节点赋值
book2_price.InnerText = "20";
book2.AppendChild(book2_price);
xml.Save("Books.xml");
Console.WriteLine("保存OK");
Console.ReadKey();
}
}
对XML增删改查
internal class Program
{
static void Main(string[] args)
{
List<Person> listPerson = new List<Person>();
listPerson.AddRange
(new Person[] {
new Person() {Name= "张三",Age=19,Gender='男' },
new Person() {Name= "李四",Age=20,Gender='女' },
new Person() {Name= "王五",Age=21,Gender='中' }});
//把集合中的数据,写入到xml文档中
//1、创建文档对象
XmlDocument doc = new XmlDocument();
//2、创建文档声明
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
doc.AppendChild(dec);
//3、创建根节点
XmlElement xmlPersons = doc.CreateElement("Persons");
doc.AppendChild(xmlPersons);
int i = 0;
//4、遍历泛型集合,把集合中的Person对象,以元素的形式,添加到XML文档中
foreach (var item in listPerson)
{
i++;
//4.1 每一个Person对象,都是一个节点
XmlElement person = doc.CreateElement("Person");
XmlAttribute att = doc.CreateAttribute("ID");
att.Value = i.ToString();
person.Attributes.Append(att);
//4.2 把创建的子节点,添加到根节点上
xmlPersons.AppendChild(person);
//4.3 给子节点,添加对应的Name、Age、Gender
XmlElement name = doc.CreateElement("Name");
name.InnerText = item.Name;
//4.4 把子节点Name,添加到根节点Person上
person.AppendChild(name);
//4.3 给子节点,添加对应的Name、Age、Gender
XmlElement age = doc.CreateElement("Age");
age.InnerText = item.Age.ToString();
//4.4 把子节点Name,添加到根节点Person上
person.AppendChild(age);
//4.3 给子节点,添加对应的Name、Age、Gender
XmlElement gender = doc.CreateElement("Gender");
gender.InnerText = item.Gender.ToString();
//4.4 把子节点Name,添加到根节点Person上
person.AppendChild(gender);
}
doc.Save("Person.xml");
Console.WriteLine("保存成功");
Console.ReadKey();
}
}
class Person
{
public string Name { get; set; }
public int Age { get; set; }
public char Gender { get; set; }
}