1.interface 接口
类可以通过 : 符号来实现一个或多个接口。类必须实现接口中定义的所有成员。
一个类可以实现多个接口。)
在这里插入代码片
2.IEventAggregator事件
IEventAggregator是一种用于实现事件聚合的设计模式。
在 Prism 框架 中,IEventAggregator 是一个核心组件,用于实现发布/订阅模式,帮助开发者实现松耦合的组件通信。
它允许组件通过发布和订阅事件进行通信,而不需要直接引用彼此。少组件之间的耦合,使代码更易于维护和扩展
常用于流程与界面之间进行通信【事件发布与处理】
需要注意:需要项目中先加入prism框架。
-
导入库文件,可以参考 (【如何新建一个应用模块】)
-
定义事件
事件是一个继承自 PubSubEvent 的类,其中 T 是事件参数的类型。
//测试发布订阅流程:第一步:定义一个自定义事件类
public class MyEventClass : PubSubEvent<string>
{
// 可以留空,除非需要特殊实现
}
- 发布事件
//测试发布订阅流程:第二步:在需要触发事件的类中发布事件
public class TestServiceClass
{
private readonly IEventAggregator _eventAggregator;
public TestServiceClass(IEventAggregator eventAggregator) {
_eventAggregator = eventAggregator;
}
public void SendMessage(string message)
{
// 获取事件并发布**********************************************************
_eventAggregator.GetEvent<MyEventClass>().Publish(message);
}
}
- 订阅事件
//测试发布订阅流程:第三步:在需要接收事件的类中订阅事件
public class TestViewModel : BindableBase //这里需要改一下
{
public string ReceivedMessage { get; private set; }
private IContainerExtension _container;
private IEventAggregator _eventAggregator;
public TestViewModel(IContainerProvider containerProvider,IEventAggregator eventAggregator)
{
//_container = containerProvider;
_eventAggregator = eventAggregator;
// 订阅事件******************************************************************
_eventAggregator.GetEvent<MyEventClass>().Subscribe(OnMessageReceived);
}
private void OnMessageReceived(string message)
{
ReceivedMessage = message;
// 处理接收到的消息...
}
}
- 使用
TestServiceClass testServiceClass = new(_eventAggregator);
testServiceClass.SendMessage("testServiceClass.SendMessage");
2.1高级用法:
//带条件的订阅
// 1.只有当消息以"Important:"开头时才处理
eventAggregator.GetEvent<MessageSentEvent>().Subscribe(OnImportantMessageReceived,
ThreadOption.PublisherThread,
false,
message => message.StartsWith("Important:"));
//2. 在UI线程上处理事件(适用于需要更新UI的情况)
eventAggregator.GetEvent<MessageSentEvent>()
.Subscribe(OnMessageReceived, ThreadOption.UIThread);
//3. 使用强引用(默认是弱引用,设置为true表示强引用)
eventAggregator.GetEvent<MessageSentEvent>()
.Subscribe(OnMessageReceived, ThreadOption.PublisherThread, true);
//4.取消引用
private SubscriptionToken _subscriptionToken;
public SubscriberViewModel(IEventAggregator eventAggregator)
{
_subscriptionToken = eventAggregator.GetEvent<MessageSentEvent>()
.Subscribe(OnMessageReceived);
}
public void Unsubscribe()
{
eventAggregator.GetEvent<MessageSentEvent>()
.Unsubscribe(_subscriptionToken); //*************************************************
}
3.IContainerExtension[views,viewModule,service]
IContainerExtension 是 Prism 框架中用于抽象依赖注入(DI)容器的接口,它提供了一种统一的方式来注册和解析依赖项。【主要跟界面有关】
用法:
- 注册依赖:将接口与实现类注册到容器中。
- 解析依赖:从容器中获取已注册的实例。
- 管理生命周期:支持单例(Singleton)、瞬态(Transient)等生命周期模式。
a.定义接口和实现类的定义.
b.APP中注册依赖《复制即可》
c.在试图模型中(viewModel)解析依赖
d.视图xaml绑定viewModel《复制即可》
可以在App中注册,将功能类service,UI显示view.xaml,UI接口viewModel.cs,形成模块。
4.BindableBase-prism
属于MVVM的知识点,为 ViewModel 提供:1.自动实现 INotifyPropertyChanged 接口。2.无需手动编写属性变更通知逻辑。3.使用 SetProperty 方法轻松管理属性变更。4.
使用:1.让你的 ViewModel 继承自 BindableBase。2.对于需要通知 UI 的属性,使用 SetProperty 方法。3.可以可选地实现属性变更的回调方法。
using Prism.Mvvm;
public class UserViewModel : BindableBase
{
private string _name;
private int _age;
public string Name
{
get => _name;
set => SetProperty(ref _name, value);
}
public int Age
{
get => _age;
set => SetProperty(ref _age, value);
}
}
一些相关的高级用法:
5.DelegateCommand-prism
DelegateCommand在xaml与viewModel之间进行通信,可将方法直接作为命令的执行逻辑,不需要创建单独的类【用于xaml和viewModel之间】
private DelegateCommand _clickCommand;
public DelegateCommand ClickCommand =>
_clickCommand ?? (_clickCommand = new DelegateCommand(ExecuteClick));
private void ExecuteClick()
{
// 执行点击操作
System.Diagnostics.Debug.WriteLine("按钮被点击了!");
}
<Button
Grid.Row="2"
Grid.Column="0"
Command="{Binding ClickCommand}"
Content="按钮点击" />
另外一种简化版本方法:
public DelegateCommand<string> ClickCommand_2 { get; private set; }
private void ExecuteClick_2(string obj)
{
Console.WriteLine("按钮2按下!");
}
//功能按钮【在构造函数中加入】
ClickCommand_2 = new DelegateCommand<string>(ExecuteClick_2);
<Button
Grid.Row="3"
Grid.Column="0"
Command="{Binding ClickCommand_2}"
Content="按钮点击2" />
6.Lambda表达式与简化写法
Lambda表达式:
// 传统委托写法
Func<int, int> square1 = delegate (int x) { return x * x; };
// Lambda表达式写法
Func<int, int> square2 = x => x * x;
Console.WriteLine(square2(5)); // 输出25
//多参数的Lambda表达式的用法
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 4)); // 输出7
//语句Lambda
Action<string> greet = name =>
{
//使用语句块
string greeting = $"Hello {name}!";
Console.WriteLine(greeting);
};
greet("world"); //输出
//其他简化写法1.方法组转换
//传统写法
List<string> names = new List<string> { "Alice","Bob","Charlie"};
names.ForEach(delegate(string name) {Console.WriteLine(name);});
//方法组转换简化
names.ForEach(Console.WriteLine);
//其他简化写法2.对象初始化简化
//传统写法
Person p1 = new Person();
p1.Name = "Alice";
p1.Age = 25;
//简化写法
Person p2 = new Person { Name = "Alice",Age = 25};
//其他简化写法3.集合初始化简化
//传统写法
List<int> numbers = new List<int>();
numbers.Add(1);
numbers.Add(2);
numbers.Add(3);
//简化写法
List<int> list = new List<int> { 1, 2, 3 };
//其他简化写法4.空条件运算符(?.)
Person person= new Person { Name = "Alice", Age = 25 }; ;
//传统写法
if((person != null) && (person.Name!=null))
{
Console.WriteLine(person.Name);
}
//简化写法
Console.WriteLine(person?.Name);
//其他简化写法5.空合并运算符(??)
//传统写法
string name = (person != null) ? person.Name : "Unkown";
//简化写法
string name1 = person?.Name ?? "Unknown";
//LINQ中的Lambda表达式
List<int> numberslist = new List<int> { 1, 2, 3 };
//筛选偶数
var events = numberslist.Where(x => x % 2 == 0);
//计算平方
var squares = numberslist.Select(x => x * x);
//排序
var ordered = numbers.OrderByDescending(x => x);
//局部函数与Lambda结合使用
bool isvalid(int x) => x > 0 && x < 100;
List<int> data = new List<int> { 0, 12 };
var validData = data.Where(x => isvalid(x));
//表达式体成员
//传统属性
public string _name;
public string Name
{
get { return _name; }
}
//表达式体属性
public string _name_2;
public string Name_2 => _name_2;
//表达式体方法
public int Square(int x) => x * x;
7.Action关键字 <为内置的委托类型>,Func
Action 是 C# 中的一个内置委托类型,用于表示没有返回值的方法。它可以用于封装方法并作为参数传递,是实现回调、事件处理和异步编程的常用工具。
无参数Action:
//无参Action的用法:
// 第一步:定义一个无参数的方法
void Greet()
{
Console.WriteLine("Hello, World!");
}
public void Test()
{
// 创建 Action 实例
Action greetAction = Greet;
// 调用 Action
greetAction(); // 输出: Hello, World!
}
带参数Action:
// 有参Action的用法: 第一步: 定义一个带参数的方法
void PrintSum(int a, int b)
{
Console.WriteLine($"Sum: {a + b}");
}
public void Test_int()
{
// 创建带参数的 Action
Action<int, int> sumAction = PrintSum;
// 调用 Action
sumAction(5, 3); // 输出: Sum: 8
}
使用场景:
public void TestAction_2_1()
{
//1.作为方法参数
void ProcessNumbers(int x, int y, Action<int, int> operation)
{
Console.WriteLine("Processing numbers...");
operation(x, y);
}
void Add(int a, int b) => Console.WriteLine($"Addition: {a + b}");
void Multiply(int a, int b) => Console.WriteLine($"Multiplication: {a * b}");
// 使用
ProcessNumbers(4, 5, Add); // 输出: Processing numbers... Addition: 9
ProcessNumbers(4, 5, Multiply); // 输出: Processing numbers... Multiplication: 20
}
public void TestAction_2_2()
{
//2.使用匿名方法
Action<string> printAction = delegate (string message)
{
Console.WriteLine(message.ToUpper());
};
//使用
printAction("hello"); //输出:HELLO
}
public void TestAction_2_3()
{
//3.使用Lambda表达式
Action<int, int> powerAction = (baseNum, exponent) =>
{
int result = (int)Math.Pow(baseNum, exponent);
Console.WriteLine($"{baseNum}^{exponent} = {result}");
};
//使用
powerAction(2, 3);
}
public void TestAction_2_4()
{
//4.多播委托
Action multiAction = () => Console.WriteLine("First action");
multiAction += () => Console.WriteLine("Second action");
multiAction();
}
在这里插入代码片
Action 与 Func 的区别:Action用于没有返回值的方法 ; Func用于有返回值的方法;
//Action与Func的区别:Action用于没有返回值的方法 ; Func用于有返回值的方法;
public void TestAction_3_1()
{
Func<int,int,int> addFunc = (a, b) =>a + b;
int result = addFunc(1, 2);
}
实际应用示例:
public void TestAction_3_1()
{
//实际应用实例1:回调机制
void DownloadData(string url, Action<string> callback)
{
Console.WriteLine($"Downloading data from {url}...");
// 模拟下载完成
string data = "Sample data";
callback(data);
}
// 使用
DownloadData("http://example.com", data =>
{
Console.WriteLine($"Data received: {data}");
});
}
public void TestAction_3_2()
{
//实际应用实例2:延迟执行
void ExecuteAfterDelay(int delayMs, Action action)
{
Thread.Sleep(delayMs);
action();
}
ExecuteAfterDelay(2000, () => Console.WriteLine("Executed after 2 seconds"));
}
public void TestAction_3_3()
{
//实际应用实例3:条件执行
void ExecuteIf(bool condition, Action action)
{
if (condition)
{
action();
}
else
{
Console.WriteLine("Action not executed");
}
}
ExecuteIf(true, () => Console.WriteLine("This will execute"));
ExecuteIf(false, () => Console.WriteLine("This won't execute"));
}
7.ref关键字
在 C# 中用于传递参数的引用而不是值,允许方法修改调用者传递的变量。在使用时加入ref关键字
基本用法:
//方法1.按引用传递参数
void ModifyValue(ref int x)
{
x = x * 2;
}
//方法1调用
int number = 5;
ModifyValue(ref number);
Console.WriteLine(number); // 输出 10
//方法2.引用返回值(C# 7.0)
ref int Find(int[] numbers, int value)
{
for (int i = 0; i < numbers.Length; i++)
{
if (numbers[i] == value)
{
return ref numbers[i];
}
}
throw new AggregateException("value not found");
}
//方法2调用:
//调用2
int[] array = {1,3,4,5};
ref int item = ref Find(array, 3);
item = 10; //直接修改数组中的元素
Console.WriteLine(string.Join(",",array)); //输出1,10,4,5
//3.引用局部变量(C# 7.0)
int a = 5;
ref int b = ref a; //b是a的引用
b = 10;
Console.WriteLine(a); //输出10
实际应用示例:
//应用1:交换两个变量的值
void Swap(ref int x, ref int y)
{
int temp = x;
x = y;
y = temp;
}
//调用:
//应用1 -使用
int a = 10; int b = 20;
Swap(ref a, ref b);
Console.WriteLine($"a = {a},b={b}"); //输出a = 20,b=10
//应用2:修改数组元素
void IncrementArrayElements(ref int[] arr)
{
for (int i = 0; i < arr.Length; i++)
{
arr[i]++;
}
}
//应用2 -使用
int[] numbers= { 1,2, 3 };
IncrementArrayElements(ref numbers);
Console.WriteLine(string.Join(",",numbers)); //输出2,3,4
ref和out对比:
ref:调用前必须初始化;可以读取或修改;双向传递数据;
out:调用前无需初始化;必须在返回前赋值;主要用于输出数据;
8.out关键字
out关键字在 C# 中用于传递参数的引用,主要用于从方法中返回多个值。
基础用法:
//out基本用法1:声明out参数
void GetValues(out int x, out string y)
{
x = 10; //必须在方法内赋值
y = "hello"; //必须在方法内赋值
}
//out基本用法1:调用
int a;
string b;
GetValues(out a, out b);
Console.WriteLine($"{a} ,{b}");
out基本用法2:方法调用时使用 out
///从C#7.0开始,可以在调用时直接声明out变量
///
GetValues(out int aa, out string bb);
Console.WriteLine($"{aa},{bb}"); //输出"10,hello"
out实际应用示例
//out实际应用示例1:TryParse模式[格式转换的一种形式]
if(int.TryParse("123",out int result))
{
Console.WriteLine($"转换成功:{result}");
}
else
{
Console.WriteLine("转换失败");
}
//out实际应用示例2:返回多个值
void GetCircleProperties(double radius, out double area, out double circumference)
{
area = Math.PI * radius * radius;
circumference = 2 * Math.PI * radius;
}
//out实际应用示例2:返回多个值,调用
GetCircleProperties(5, out double a, out double c);
Console.WriteLine($"面积: {a}, 周长: {c}");
//out实际应用示例3:交换变量值
void Swap(out int x, out int y, int a, int b)
{
x = b;
y = a;
}
//out实际应用示例3:交换变量值,调用
int first = 10, second = 20;
Swap(out first, out second, first, second);
Console.WriteLine($"first: {first}, second: {second}"); // first: 20, second: 10
高级用法:
//Out高级用法1:接口中的out参数(协变)
public interface Interface_TestOut<T>
{
bool TryProcess(out T result);
}
//Out高级用法1:接口中的out参数(协变)
public class TestOutItf_Class : Interface_TestOut<string>
{
public bool TryProcess(out string result)
{
result = "Processed";
return true;
}
}
//out高级用法2:元组与out结合
var dict = new Dictionary<string, int> { ["one"] = 1, ["two"] = 2};
if(dict.TryGetValue("one",out var value))
{
Console.WriteLine(value);
}
9.static关键字
主要用于创建类级别的成员而不是实例级别的成员
静态类【静态类不能被实例化,只能包含静态成员】
静态字段【静态字段属于类而不是实例,所有实例共享同一个静态字段】
静态方法【静态方法属于类而不是实例,不能访问实例成员】
静态构造函数【用于初始化静态字段,在类第一次被使用前自动调用】
静态属性【可使用类名.属性进行读取与修改】
静态成员常用于工具类、共享数据、单例模式等场景,可以避免不必要的对象实例化,提高性能。
10.索引器this关键字
它允许对象像数组一样通过索引来访问。索引器类似于属性,但使用索引而不是属性名来访问。
索引器提供了一种方便的方式来访问类或结构中的数据,使得对象可以像数组或集合一样被访问,提高了代码的可读性和易用性
简单示例:
class StringArray
{
private string[] array = new string[5];
// 索引器定义
public string this[int index]
{
get
{
if (index < 0 || index >= array.Length)
throw new IndexOutOfRangeException();
return array[index];
}
set
{
if (index < 0 || index >= array.Length)
throw new IndexOutOfRangeException();
array[index] = value;
}
}
}
// 使用示例
StringArray sa = new StringArray();
sa[0] = "Hello"; // 调用set访问器
Console.WriteLine(sa[0]); // 调用get访问器,输出"Hello"
可以使用除开整数类型的其他类型的索引(例如字符串)
class Dictionary
{
private Dictionary<string, string> dict = new Dictionary<string, string>();
public string this[string key]
{
get { return dict[key]; }
set { dict[key] = value; }
}
}
// 使用示例
Dictionary d = new Dictionary();
d["name"] = "John";
Console.WriteLine(d["name"]); // 输出"John"
使用多个索引(类似二维数组)
class Matrix
{
private int[,] data = new int[3, 3];
public int this[int row, int col]
{
get { return data[row, col]; }
set { data[row, col] = value; }
}
}
// 使用示例
Matrix m = new Matrix();
m[0, 0] = 1;
m[1, 1] = 2;
Console.WriteLine(m[0, 0]); // 输出1
索引器与属性的区别:1.索引器使用this关键字定义,属性使用名称定义。2.
11.var关键字
var是 C# 3.0 引入的一个隐式类型关键字,它允许编译器根据初始化表达式自动推断变量的类型。
使用场景1:简化复杂类型声明
// 不使用 var
Dictionary<string, List<Employee>> employeeGroups = new Dictionary<string, List<Employee>>();
// 使用 var
var employeeGroups = new Dictionary<string, List<Employee>>();
var person = new { Name = "Alice", Age = 25 };
Console.WriteLine($"{person.Name} is {person.Age} years old");
需要注意:使用 var 时必须同时初始化变量;不能用于字段:只能在方法内部使用;
// 方法返回值
var stream = File.OpenRead("test.txt");
// foreach 循环
foreach (var item in collection) { ... }
11.字典的常用用法【C#字典常用用法及示例】
Dictionary<TKey, TValue> 是 C# 中常用的键值对集合,提供了高效的查找、添加和删除操作
//1. 创建空字典
Dictionary<string, int> ages = new Dictionary<string, int>();
//2. 添加
ages.Add("Alice", 95); // 使用 Add 方法
ages["Bob"] = 88; // 使用索引器添加
//3. 创建并初始化字典
Dictionary<string, string> capitals = new Dictionary<string, string>
{
{"China", "Beijing"},
{"USA", "Washington D.C."},
{"Japan", "Tokyo"}
};
//4. 访问元素
//4.1使用索引器访问
string appleColor = colors["apple"]; // "red"
//4.2使用 TryGetValue 安全访问
if (colors.TryGetValue("banana", out string bananaColor))
{
Console.WriteLine(bananaColor); // "yellow"
}
//5. 检查键是否存在
if (students.ContainsKey(101))
{
Console.WriteLine("Student 101 exists.");
}
//6.遍历
// 遍历键值对
foreach (KeyValuePair<string, decimal> item in prices)
{
Console.WriteLine($"{item.Key}: ${item.Value}");
}
// 只遍历键
foreach (string key in prices.Keys)
{
Console.WriteLine(key);
}
// 只遍历值
foreach (decimal value in prices.Values)
{
Console.WriteLine(value);
}
//7.修改和删除元素
// 修改值
inventory["Apples"] = 45;
// 删除元素
inventory.Remove("Oranges");
// 清空字典
inventory.Clear();
12.List列表的常用用法【C#中List的用法及优点总结】
创建一个空列表
List<int> numbers = new List<int>();
// 创建并初始化列表
List<string> fruits = new List<string>() { "Apple", "Banana", "Orange" };
//添加元素
fruits.Add("Red");
//删除元素
numbers.Remove(4); // 删除第一个出现的4
numbers.RemoveAt(0); // 删除索引0的元素
numbers.RemoveAll(n => n > 3); // 删除所有大于3的元素
numbers.Clear(); // 清空整个列表
//查找元素
List<string> names = new List<string> { "Alice", "Bob", "Charlie" };
bool containsBob = names.Contains("Bob"); // true
int index = names.IndexOf("Charlie"); // 返回2
string found = names.Find(name => name.StartsWith("A")); // "Alice"
13.另外类的常用用法【转盘数据data】
流程中使用:
private DutData _dutData; //在整个流程中定义
//获取当前数据:
_dutData = HandleDutDataFunc.GetDutData(HandleDutDataFunc.Station.Station1);
/// <summary>
/// 获取指定工站DutData
/// </summary>
/// <param name="station">工站名</param>
public static DutData GetDutData(Station station)
{
return _dic[station];
}
private static Dictionary<Station, DutData> _dic = [];
public enum Station
{
Station1,
Station2,
Station3,
Station4
}
//修改字典内容:转盘转动之后挪动
public static void UpdateDutData(RunDirection runDirection)
{
DutData temp = _dic[Station.Station1];
if (runDirection == RunDirection.CommonDirection)
{
_dic[Station.Station1] = _dic[Station.Station4];
_dic[Station.Station4] = _dic[Station.Station3];
_dic[Station.Station3] = _dic[Station.Station2];
_dic[Station.Station2] = temp;
}
else
{
_dic[Station.Station1] = _dic[Station.Station2];
_dic[Station.Station2] = _dic[Station.Station3];
_dic[Station.Station3] = _dic[Station.Station4];
_dic[Station.Station4] = temp;
}
}
/// <summary>
/// 为指定工站DutData赋值
/// </summary>
/// <param name="station">工站名</param>
/// <param name="dutData">数据</param>
public static void SetDutData(Station station, DutData dutData)
{
_dic[station] = dutData;
}
struct 结构体 与 class类的区别
类型 值类型 (Value Type) 引用类型 (Reference Type)
内存分配 直接包含数据 包含对数据的引用
修改影响 修改副本不影响原始值 修改引用对象会影响所有引用
13.数据库
Entity Framework Core
using Microsoft.EntityFrameworkCore;
// 定义数据库上下文
public class AppDbContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=localhost;Database=TestDB;User Id=username;Password=password;");
}
}
/ 确保数据库已创建
context.Database.EnsureCreated();
// 添加数据
var customer = new Customer { Name = "Jane Smith", Email = "jane@example.com" };
context.Customers.Add(customer);
context.SaveChanges();
Console.WriteLine("数据已添加");
// 查询数据
var customers = context.Customers.ToList();
foreach (var c in customers)
{
Console.WriteLine($"ID: {c.Id}, Name: {c.Name}, Email: {c.Email}");
}
// 更新数据
var customerToUpdate = context.Customers.First();
customerToUpdate.Name = "Updated Name";
context.SaveChanges();
14.phase【多线程用法】
List<Task> tasks = [];
foreach (var phase in _phases)
{
tasks.Add(Task.Run(() =>
{
phase.WaitTaskDone(timeoutInMs);
}));
}
Task.WaitAll(tasks.ToArray());
4.委托
MVVM