1.10. C# 编程实例
1.10.1. 实例一:文件批量重命名工具
BatchRename.cs
using System.Text.RegularExpressions;
public static class BatchRename
{
/// <summary>
/// 批量重命名文件
/// </summary>
/// <param name="directory">目标目录</param>
/// <param name="pattern">搜索模式 如 "*.txt"</param>
/// <param name="replaceFunc">重命名函数</param>
/// <returns>重命名的文件数量</returns>
public static int RenameFiles(
string directory,
string pattern,
Func<string, string> replaceFunc)
{
var files = Directory.GetFiles(directory, pattern);
int count = 0;
foreach (var filePath in files)
{
var dir = Path.GetDirectoryName(filePath)!;
var fileName = Path.GetFileName(filePath);
var newName = replaceFunc(fileName);
if (newName != fileName)
{
var newPath = Path.Combine(dir, newName);
File.Move(filePath, newPath);
count++;
Console.WriteLine($"重命名: {fileName} -> {newName}");
}
}
return count;
}
}
// 使用示例
// 添加前缀:"IMG_" + 原文件名
BatchRename.RenameFiles(@"C:\Photos", "*.jpg",
name => $"IMG_{name}");
// 替换空格为下划线
BatchRename.RenameFiles(@"C:\Docs", "*.pdf",
name => name.Replace(" ", "_"));
// 序号重命名(正则匹配)
int seq = 1;
BatchRename.RenameFiles(@"C:\Data", "*.csv",
name => $"{seq++:D4}_{name}");
1.10.2. 实例二:日志分析工具
LogParser.cs
public class LogEntry
{
public DateTime Timestamp { get; set; }
public string Level { get; set; } = "";
public string Message { get; set; } = "";
public string? Source { get; set; }
}
public class LogParser
{
private static readonly Regex LogPattern = new(
@"^\[(?<time>.*?)\]\s\[(?<level>\w+)\]\s(?<message>.*)$",
RegexOptions.Compiled);
public async IAsyncEnumerable<LogEntry> ParseAsync(
string filePath,
[EnumeratorCancellation] CancellationToken ct = default)
{
await foreach (var line in File.ReadLinesAsync(filePath, ct))
{
ct.ThrowIfCancellationRequested();
var match = LogPattern.Match(line);
if (match.Success)
{
yield return new LogEntry
{
Timestamp = DateTime.Parse(match.Groups["time"].Value),
Level = match.Groups["level"].Value,
Message = match.Groups["message"].Value,
};
}
}
}
public async Task<LogSummary> AnalyzeAsync(
string filePath, CancellationToken ct = default)
{
var summary = new LogSummary();
await foreach (var entry in ParseAsync(filePath, ct))
{
summary.Total++;
if (!summary.LevelCount.ContainsKey(entry.Level))
summary.LevelCount[entry.Level] = 0;
summary.LevelCount[entry.Level]++;
if (entry.Level == "ERROR")
summary.Errors.Add(entry);
}
return summary;
}
}
public class LogSummary
{
public int Total { get; set; }
public Dictionary<string, int> LevelCount { get; set; } = new();
public List<LogEntry> Errors { get; set; } = new();
public void PrintReport()
{
Console.WriteLine($"总计日志数: {Total}");
Console.WriteLine($"错误数: {Errors.Count}");
Console.WriteLine("\n级别统计:");
foreach (var (level, count) in LevelCount
.OrderByDescending(x => x.Value))
{
var bar = new string('#', count * 40 / Total);
Console.WriteLine($" {level,-12} {count,6} {bar}");
}
}
}
1.10.3. 实例三:MVVM 待办事项应用(WPF)
1.10.3.1. Model
public class TodoItem
{
public int Id { get; set; }
public string Title { get; set; } = "";
public bool IsCompleted { get; set; }
public DateTime CreatedAt { get; set; } = DateTime.Now;
public Priority Priority { get; set; } = Priority.Medium;
}
public enum Priority { Low, Medium, High }
1.10.3.2. ViewModel
public class TodoViewModel : ViewModelBase
{
private readonly ObservableCollection<TodoItem> _items = new();
public ObservableCollection<TodoItem> Items => _items;
private string _newItemTitle = "";
public string NewItemTitle
{
get => _newItemTitle;
set
{
SetProperty(ref _newItemTitle, value);
AddCommand.RaiseCanExecuteChanged();
}
}
private TodoItem? _selectedItem;
public TodoItem? SelectedItem
{
get => _selectedItem;
set => SetProperty(ref _selectedItem, value);
}
public IEnumerable<TodoItem> PendingItems
=> Items.Where(i => !i.IsCompleted);
public IEnumerable<TodoItem> CompletedItems
=> Items.Where(i => i.IsCompleted);
public RelayCommand AddCommand { get; }
public RelayCommand<TodoItem> ToggleCommand { get; }
public RelayCommand<TodoItem> DeleteCommand { get; }
public TodoViewModel()
{
AddCommand = new RelayCommand(
execute: _ =>
{
Items.Add(new TodoItem
{
Id = Items.Count + 1,
Title = NewItemTitle,
Priority = Priority.Medium
});
NewItemTitle = "";
},
canExecute: _ => !string.IsNullOrWhiteSpace(NewItemTitle));
ToggleCommand = new RelayCommand<TodoItem>(
execute: item =>
{
item.IsCompleted = !item.IsCompleted;
OnPropertyChanged(nameof(PendingItems));
OnPropertyChanged(nameof(CompletedItems));
});
DeleteCommand = new RelayCommand<TodoItem>(
execute: item =>
{
Items.Remove(item);
});
}
}
1.10.3.3. View(MainWindow.xaml)
<Window x:Class="TodoApp.MainWindow"
Title="待办事项" Height="450" Width="500">
<Grid Margin="12">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- 添加新任务 -->
<StackPanel Orientation="Horizontal" Grid.Row="0"
Margin="0,0,0,12">
<TextBox Text="{Binding NewItemTitle}"
Width="350" PlaceholderText="输入新任务..."/>
<Button Content="添加" Command="{Binding AddCommand}"
Width="80" Margin="10,0,0,0"/>
</StackPanel>
<!-- 任务列表 -->
<ListBox Grid.Row="1"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox IsChecked="{Binding IsCompleted}"
Command="{Binding
DataContext.ToggleCommand,
RelativeSource={RelativeSource
AncestorType=Window}}"
CommandParameter="{Binding}"/>
<TextBlock Text="{Binding Title}"
FontSize="14"
TextDecorations="{Binding IsCompleted,
Converter={StaticResource StrikeConverter}}"
Margin="8,0"/>
<TextBlock Text="{Binding Priority}"
Foreground="Gray" FontSize="12"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!-- 统计信息 -->
<TextBlock Grid.Row="2" Margin="0,12,0,0">
<Run Text="总计:"/><Run Text="{Binding Items.Count}"/>
<Run Text=" 已完成:"/>
<Run Text="{Binding CompletedItems.Count}"/>
<Run Text=" 待完成:"/>
<Run Text="{Binding PendingItems.Count}"/>
</TextBlock>
</Grid>
</Window>