匿名函数
概念:没有名字的函数,一般情况下只调用一次。它的本质就是一个方法,虽然我们没有定义这个方法,但是编译器会把匿名函数编译成一个方法
public delegate void Del1();//无参数无返回值的委托
public delegate void Del2(string name);//有参数无返回值的委托
public delegate string Del3(string s,int n);//有参数有返回值的委托
internal class Program
{
static void Main(string[] args)
{
Del1 del1 = delegate ()
{
Console.WriteLine("无参数无返回值的匿名函数");
};
del1.Invoke();
Console.ReadKey();
}
}
我们可以使用lambda表达式更简洁地定义一个匿名函数
Del1 del1 = () => { Console.WriteLine("无参数无返回值的lambda表达式"); };
del1.Invoke();//调用
Console.ReadKey();
当lambda表达式中参数列表只有一个参数时,括号可以省略
Del2 del2 = msg => { Console.WriteLine("hello" + msg); };
del2.Invoke("world" + "有参数无返回值的lambda表达式");
Console.ReadKey();
匿名函数定义的参数列表的参数类型,是不能省略的
Del3 dle3 = (string s1, int n1) => { return "有参数有返回值的lambda表达式"; };
string res = dle3.Invoke("1", 1);
Console.WriteLine(res);
泛型委托
之前我们写的委托都是需要自己定义委托的参数和返回值,而.NET框架为我们封装了泛型委托框架,让我们不用再声明委托,可以直接使用。分别为Action委托,Func委托。
Action委托:
不带返回值的委托,可以有参数,也可以没有参数
Action action = () => { Console.WriteLine("无参无返回值的委托"); };
action();//直接调用
action.Invoke();//间接调用
Action<string,int> action2 = (a,b)=> { Console.WriteLine("姓名为{0}的人,年龄为{1}",a,b); };
action2.Invoke("张三",18);
Console.ReadKey();
Func委托:
带返回值的委托
//如果Func尖括号里只有一个参数类型,就表示返回值就是这个类型
Func<int> func = () => { return 100; };
int a = func.Invoke();
Console.WriteLine(a);
//需要两个整数类型的参数,以及一个string类型的返回值
Func<int, int, string> func2 = (c, d) => { Console.WriteLine(c); Console.WriteLine(d); return "hello world"; };
string res = func2.Invoke(10, 20);
Console.WriteLine(res);
使用委托进行窗体传值
1、先创建两个窗体对象,添加所需控件
2、当点击form1按钮时,将textbox里的值传递给form2
namespace 委托_窗体传值
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//创建一个form2对象,通过form2的构造函数将窗体1的文本框的值传递给窗体2
Form2 form2 = new Form2(textBox1.Text.Trim());
//将窗体2展示出来
form2.Show();
}
}
}
namespace 委托_窗体传值
{
public partial class Form2 : Form
{
public Form2(string msg)//窗体2的构造函数,每回创建窗体2对象的时候都会执行构造函数初始化。通过参数接收窗体一传递过来的值
{
InitializeComponent();
textBox1.Text = msg;//将接收到的值展示到窗体2的文本框上
}
private void button1_Click(object sender, EventArgs e)
{
}
}
}
3、当点击form2的按钮时,将窗体2中的值传递给窗体1
public partial class Form2 : Form
{
string _msg;//字段存储窗体二收到的消息
Action<string> _action;
public Form2(string msg,Action<string> action)//窗体2的构造函数,每回创建窗体2对象的时候都会执行构造函数初始化。通过参数接收窗体一传递过来的值
{
InitializeComponent();
//textBox1.Text = msg;//将接收到的值展示到窗体2的文本框上
this._msg = msg;
this._action = action;
}
private void button1_Click(object sender, EventArgs e)
{
//调用ShowMsg,将值传递给窗体1
this._action.Invoke(textBox1.Text.Trim());
}
private void Form2_Load(object sender, EventArgs e)
{
//窗体加载的时候,把数据赋值给文本框
textBox1.Text = this._msg;
}
}
namespace 委托_窗体传值
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//创建一个form2对象,通过form2的构造函数将窗体1的文本框的值传递给窗体2
Form2 form2 = new Form2(textBox1.Text.Trim(),ShowMsg);
//将窗体2展示出来
form2.Show();
}
void ShowMsg(string msg)
{
textBox1.Text = msg;
}
}
}
多播委托
概念:让一个委托对象,指向多个方法
internal class Program
{
public delegate void Del();
static void Main(string[] args)
{
Del del = M1;
del += M2;
del += M3;
del += M4;
del -= M5;
del.Invoke();
Console.ReadKey();
}
static void M1()
{
Console.WriteLine("我是M1");
}
static void M2()
{
Console.WriteLine("我是M2");
}
static void M3()
{
Console.WriteLine("我是M3");
}
static void M4()
{
Console.WriteLine("我是M4");
}
static void M5()
{
Console.WriteLine("我是M5");
}
}
运行结果
反射
概念:反射就是动态获取程序集中的元数据(提供程序集的类型信息)的功能
internal class Program
{
static void Main(string[] args)
{
//Type
//获取类型的类型:元数据
//获取类型的Type有两种方式
//1、创建了Person对象
//Person p = new Person();
//Type type = p.GetType();
//2、没有创建Person对象
Type type = typeof(Person); //typeof后面放的是数据类型,不能放对象
//GetMembers()获取type反射出来所有的类型中的公共成员
MemberInfo[] mi = type.GetMembers(BindingFlags.Instance|BindingFlags.NonPublic);
foreach (var item in mi)
{
Console.WriteLine(item.Name);
}
Console.ReadKey();
}
}
class Person
{
public Person()
{
}
private string _name;
public int Age { get; set; }
public void SayHi()
{
Console.WriteLine("实例方法");
}
public static void StaticSayHi()
{
Console.WriteLine("静态方法");
}
public Person(string name, int age)
{
this._name = name;
this.Age = age;
}
public Person(int age)
{
this.Age = age;
}
}
反射程序集中的元数据
internal class Program
{
static void Main(string[] args)
{
//1、先获取要反射数据的程序集
//注意:就把ass这个程序集对象,当成是DLL类库
Assembly ass = Assembly.LoadFile(@"C:\Users\ThinkPad\source\repos\DLL_Test\bin\Debug\DLL_Test.dll");
//2、获取程序集中定义的数据类型/成员 GetTypes获取的成员包括public和internal修饰的
//Type[] types = ass.GetTypes();
//GetExportedTypes();获取所有被public修饰的成员
//Type[] types = ass.GetExportedTypes();
//foreach (var item in types)
//{
// Console.WriteLine(item.Name);
//}
//GetType():在类型的名字前面,必须加上命名空间
Type type = ass.GetType("DLL_Test.Person");
//class:类
//Method:方法
//field:字段
//Property:属性
//Instance:实例的
//static:静态的
//Assembly:程序集
//Type:类型
//Exported:公开的
//Member:成员
//Parameter:参数
//Constructor:构造函数
//GetMembers()获取类型中定义的所有公开成员
//MemberInfo[] mi = type.GetMembers(BindingFlags.Instance | BindingFlags.NonPublic);
//foreach (var item in mi)
//{
// Console.WriteLine(item.Name);
//}
//3、获取类型中定义的所有的方法
//MethodInfo[] mi = type.GetMethods();
//foreach (var item in mi)
//{
// Console.WriteLine(item.Name);
// //Console.WriteLine(item.ReturnParameter.Name);
// Console.WriteLine(item.ReturnType); //获取返回值的类型
// Console.WriteLine("==============================");
//}
4、获取类型中定义的所有构造函数
//ConstructorInfo[] ci = type.GetConstructors();
//foreach (var item in ci)
//{
// Console.WriteLine(item.Name);
// ParameterInfo[] pi = item.GetParameters();
// foreach (var item2 in pi)
// {
// Console.WriteLine(item2.Name);
// //获取参数类型
// Console.WriteLine(item2.ParameterType);
// Console.WriteLine("==============================================");
// }
//}
//5、获取数据类型中定义的所有属性
//PropertyInfo[] pi = type.GetProperties();
//foreach (var item in pi)
//{
// Console.WriteLine(item.Name);
//}
//6、获取数据类型中定义的所有字段
//FieldInfo[] fi = type.GetFields(BindingFlags.Instance|BindingFlags.NonPublic);
//foreach (var item in fi)
//{
// Console.WriteLine(item.Name);
//}
//7、调用静态方法
//MethodInfo[] mi = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
//foreach (var item in mi)
//{
// Console.WriteLine(item);
//}
//MethodInfo mi = type.GetMethod("StaticSayHi");
调用
参数1:表示实例对象,调用静态方法,可以不提供,给null值即可。
参数2:表示方法的参数,必须以object数组的形式提供。
//object res = mi.Invoke(null, new object[] { "world" });
//Console.WriteLine(res);
8、调用实例方法
//MethodInfo mi = type.GetMethod("InstanceSayHi");
动态的创建对象 CreateInstance帮我们执行构造函数,创建对象
//object o = Activator.CreateInstance(type);
//mi.Invoke(o, null);
//9、调用重载方法 new Type[] { typeof(int), typeof(int) } 来匹配重载
//MethodInfo mi = type.GetMethod("Add", new Type[] { typeof(int), typeof(int) });
//object o = Activator.CreateInstance(type);
//object res = mi.Invoke(o, new object[] { 1,1 });
//Console.WriteLine(res);
//10、调用构造函数
ConstructorInfo ci = type.GetConstructor(new Type[] { });
object o = ci.Invoke(null);
Console.ReadKey();
}
}
反射相关的补充方法
internal class Program
{
static void Main(string[] args)
{
//IsAssignableFrom: 后面的是否可以赋值给前面的
//特点:既可以判断类,也可以判断接口
//bool b = typeof(Person).IsAssignableFrom(typeof(Teacher));
//bool b2 = typeof(I1).IsAssignableFrom(typeof(Teacher));
//IsInstanceOfType:后面的对象,是否可以赋值给前面的类型
Person p = new Person();
Student s = new Student();
Teacher t = new Teacher();
//bool b3 = typeof(Person).IsInstanceOfType(p);
//bool b4 = typeof(Person).IsInstanceOfType(s);
//bool b5 = typeof(Person).IsInstanceOfType(t);
//bool b6 = typeof(I2).IsInstanceOfType(t);
//Console.WriteLine(b3);
//Console.WriteLine(b4);
//Console.WriteLine(b5);
//Console.WriteLine(b6);
//IsSubclassOf 跟接口没关系
bool b = t.GetType().IsSubclassOf(typeof(I2));
//Console.WriteLine(b);
Console.WriteLine(typeof(Animal).IsAbstract);
Console.WriteLine(typeof(Person).IsAbstract);
Console.WriteLine(typeof(I2).IsAbstract);
Console.ReadKey();
}
}
class Person
{
}
class Student : Person
{ }
abstract class Animal
{ }
interface I1
{
}
interface I2 : I1 { }
class Teacher : I2
{ }
记事本插件开发
1、Form1
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;
using Plug_in_Rule_DLL;
namespace _10_记事本插件开发
{
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, "Plug-in-Components");
//2、读取该路径下所有的插件
string[] files = Directory.GetFiles(path);
//3、通过Assembly去加载程序集
foreach (var file in files)
{
//4、获取到当前循环到的插件程序集
Assembly ass = Assembly.LoadFile(file);
//5、获取程序集中的元数据
//types:都是程序集中的数据类型。(类、接口、抽象类、委托、事件、.......)
Type[] types = ass.GetExportedTypes();
//6、对types做筛选
foreach (var type in types)
{
//筛选条件:1、实现了Plug_in_Rule接口的类 2、不能接口或者抽象类
if (typeof(Plug_in_Rule).IsAssignableFrom(type) && !type.IsAbstract)
{
//7、获取类型中的属性和方法
//动态的创建插件的对象
object o = Activator.CreateInstance(type);
Plug_in_Rule pir = (Plug_in_Rule)o;
//调用Name属性,赋值给Menustrip
ToolStripItem tsi = menuStrip1.Items.Add(pir.Name);
//8、给添加的小选项卡设置单击事件
tsi.Click += Tsi_Click;
//9、把pir接口,从Load方法中,传到Tsi_Click中
tsi.Tag = pir;
}
}
}
//通过反射,获取程序集中的数据:Name ChangeText()
//把Name加载到Menustrip菜单中,给菜单注册一个单击事件
//单击的时候,执行ChangeText
}
//单击选项卡的时候,调用ChangeText()
private void Tsi_Click(object sender, EventArgs e)
{
//sender 事件是谁的,sender就是谁
ToolStripItem tsi = sender as ToolStripItem;
Plug_in_Rule p = (Plug_in_Rule)tsi.Tag;
p.ChangeText(textBox1);
}
}
}
2、Plug_in_Rule 插件开发的接口规范
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Plug_in_Rule_DLL
{
/// <summary>
/// 插件开发的接口规范
/// </summary>
public interface Plug_in_Rule
{
//接口中的只读属性,不是自动属性
string Name { get; }
//让插件开发人员,实现该方法,对文本的样式进行修改
void ChangeText(TextBox textBox);
}
}
3、Str_To_Lower 全部转小写功能
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plug_in_Rule_DLL;
using System.Windows.Forms;
namespace Str_To_Lower_DLL
{
public class Str_To_Lower : Plug_in_Rule
{
public string Name { get { return "全部转小写!!!!!"; } }
public void ChangeText(System.Windows.Forms.TextBox textBox)
{
textBox.Text = textBox.Text.ToLower();
}
}
}
4、Str_To_Upper 全部转大写功能
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Plug_in_Rule_DLL;
using System.Windows.Forms;
namespace Str_To_Upper_DLL
{
/// <summary>
/// 要拓展插件功能的人
/// </summary>
public class Str_To_Upper : Plug_in_Rule
{
public string Name { get { return "全部转大写!!!!"; } }
public void ChangeText(System.Windows.Forms.TextBox textBox)
{
textBox.Text = textBox.Text.ToUpper();
}
}
}