c# - 属性挂钩 MSBuild/Roslyn
问题描述
如果我想创建一个挂钩到 .NET 构建过程并转换/转换标准 C# 自动属性的属性(从 System.Attribute 派生),例如:
[Notify]
public string Name { get; set; }
到此代码,然后编译:
private string _nameField;
public string Name
{
get => _nameField;
set
{
if (!EqualityComparer<string>.Default.Equals(_nameField, value))
{
_nameField = value;
NotifyPropertyChanged(nameof(Name));
}
}
}
我将如何实现它?我该怎么办?如何让属性挂钩到构建中?如您所见,我对构建过程和 Roslyn 都一无所知。但我想摆脱多余的 MVVM 样板代码,不再花太多时间进行枯燥的重复输入......
谢谢,克里斯
解决方案
为此有一个Fody编织器,称为PropertyChanged。
Fody 是一个用于在编译过程结束时修改代码的系统。PropertyChanged 编织器自动为所有实现的类中的所有属性实施更改通知INotifyPropertyChanged
。它有多种使用属性、实现方法等来控制生成的方法。
他们的 GitHub 项目页面中的示例是这样开始的:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName => $"{GivenNames} {FamilyName}";
}
编织器解释上述内容并生成如下代码:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
string givenNames;
public string GivenNames
{
get => givenNames;
set
{
if (value != givenNames)
{
givenNames = value;
OnPropertyChanged(InternalEventArgsCache.GivenNames);
OnPropertyChanged(InternalEventArgsCache.FullName);
}
}
}
string familyName;
public string FamilyName
{
get => familyName;
set
{
if (value != familyName)
{
familyName = value;
OnPropertyChanged(InternalEventArgsCache.FamilyName);
OnPropertyChanged(InternalEventArgsCache.FullName);
}
}
}
public string FullName => $"{GivenNames} {FamilyName}";
protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
{
PropertyChanged?.Invoke(this, eventArgs);
}
}
internal static class InternalEventArgsCache
{
internal static PropertyChangedEventArgs FamilyName = new PropertyChangedEventArgs("FamilyName");
internal static PropertyChangedEventArgs FullName = new PropertyChangedEventArgs("FullName");
internal static PropertyChangedEventArgs GivenNames = new PropertyChangedEventArgs("GivenNames");
}
当然,您将无法访问该版本,因为它发生在编译过程结束时的某个地方,并且您的源代码不受影响。调试代码可能有点困难。
为了帮助实现这一点,PropertyChanged 编织器会查找与各种规则匹配的预实现方法并生成代码来调用这些方法。如果您OnPropertyChanged
在类中有一个方法,它将调用它而不是生成样板版本。或者您可以OnFamilyNameChanged
在上面的类中添加一个方法,该方法将在该OnPropertyChanged
方法之前调用。
推荐阅读
- javascript - React Hooks 状态更改没有通过适当的道具传递
- mysql - Mysql cli 未在 crontab 运行的 bash 脚本中返回数据
- wordpress - 如何检查,我的主机是否支持 http2?
- ruby-on-rails - 如何显示 Rails API 调用数据?
- android - 如何使用 NotificationListener 服务解决极度耗电问题
- algorithm - 将矩阵分解为更小的子列表
- javascript - 如何使用 Puppeteer 将数据写入文件?
- macos - 在 Mac 上使用以太网电缆将 VNC 插入 Raspberry Pi 3B+ 当 Mac 上的 wifi 打开时,OSX 失去连接
- java - 有人可以为我解释以下代码的含义是什么
- google-apps-script - 加速电子表格的脚本(GAS - Google App Script & Google Sheets)