CsvHelper是一个用于读写CSV(逗号分隔值)文件的开源.NET库。它提供了简单而强大的API,使得处理CSV文件变得轻而易举。本文将详细介绍CsvHelper的使用方法,并提供多个实用的例子。
首先,通过NuGet包管理器安装CsvHelper:
C#Install-Package CsvHelper

MediatR是一个轻量级的中介者模式实现库,用于在.NET应用程序中处理进程内消息传递。它有助于降低代码耦合度,提高可维护性和可测试性。本文将深入探讨MediatR的使用方法,并提供多个实际示例。
在深入示例之前,让我们先了解MediatR的几个核心概念:
首先,通过NuGet包管理器安装MediatR:
Markdowndotnet add package MediatR

在C#的WinForms应用程序开发中,父子窗体之间的数据传递是一个常见且重要的话题。本文将详细介绍几种实现父子窗体传值的方法,并提供丰富的代码示例。
这是最简单直接的方法,适用于在创建子窗体时就知道要传递的值的情况。
C#// 父窗体
public partial class ParentForm : Form
{
public ParentForm()
{
InitializeComponent();
}
private void btnOpenChild_Click(object sender, EventArgs e)
{
string message = "Hello from Parent!";
ChildForm childForm = new ChildForm(message);
childForm.Show();
}
}
// 子窗体
public partial class ChildForm : Form
{
public ChildForm(string message)
{
InitializeComponent();
lblMessage.Text = message;
}
}

S7netplus 是一个开源的库,主要用于.NET环境中与西门子S7系列PLC进行通信。这个库允许开发者使用C#或其他.NET支持的编程语言来读写PLC的数据块、输入输出、标记等,非常适合于工业自动化领域的应用开发。
使用S7-PLCSIM Advanced 3.0/4.0/5.0 仿真

如果启动许可证找不到,在服务中启动





在C#这样的静态类型语言中,鸭子类型(Duck Typing)通常不像在动态语言中那样自然。鸭子类型的核心思想是:"如果它走起来像鸭子,叫起来像鸭子,那么它就是鸭子"—— 即关注对象的行为而非其类型。本文将详细介绍如何在C#中通过缓存和表达式树技术实现高性能的鸭子类型模式,以及这种模式在实际项目中的应用。
在传统C#开发中,我们通常通过接口来定义行为规范。但这种方式要求所有类型显式实现接口,缺乏灵活性。使用反射可以解决这个问题,但会带来严重的性能损失。那么如何在保持鸭子类型灵活性的同时,又能获得接近原生代码的性能呢?
我们将使用三种关键技术来实现高性能的鸭子类型:
下面我们将构建一个智能日志系统,它可以记录任何拥有GetLogMessage()方法的对象,无需这些对象实现特定接口。
C#using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace AppDuck
{
public class CachedDuckTypingLogger
{
// 缓存委托:Type => Func<object, string>
private readonly ConcurrentDictionary<Type, Func<object, string>> _messageGetterCache =
new ConcurrentDictionary<Type, Func<object, string>>();
/// <summary>
/// 记录任何具有GetLogMessage方法的对象
/// </summary>
public void Log(object item)
{
try
{
// 获取日志消息获取器
var messageGetter = GetOrCreateMessageGetter(item.GetType());
if (messageGetter != null)
{
// 获取并记录消息
string message = messageGetter(item);
Console.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {message}");
}
else
{
Console.WriteLine($"[ERROR] 无法记录类型为 {item.GetType().Name} 的对象 - 未实现GetLogMessage方法");
}
}
catch (Exception ex)
{
Console.WriteLine($"[ERROR] 记录时发生异常: {ex.Message}");
}
}
/// <summary>
/// 从缓存获取或创建消息获取委托
/// </summary>
private Func<object, string> GetOrCreateMessageGetter(Type type)
{
return _messageGetterCache.GetOrAdd(type, t =>
{
// 查找GetLogMessage方法
MethodInfo method = t.GetMethod("GetLogMessage", Type.EmptyTypes);
if (method == null || method.ReturnType != typeof(string))
return null;
// 创建表达式树
ParameterExpression param = Expression.Parameter(typeof(object), "obj");
UnaryExpression convertedParam = Expression.Convert(param, t);
MethodCallExpression methodCall = Expression.Call(convertedParam, method);
// 编译表达式树为委托
return Expression.Lambda<Func<object, string>>(methodCall, param).Compile();
});
}
}
}