[英]Attribute hooking MSBuild/Roslyn
If I wanted to create a Attribute (derived from System.Attribute) that hooks into the .NET Build process and translates/converts a standard C# auto property like:如果我想创建一个与 .NET 构建过程挂钩并转换/转换标准 C# 自动属性的属性(派生自 System.Attribute),例如:
[Notify]
public string Name { get; set; }
to this code, which then is compiled:到此代码,然后编译:
private string _nameField;
public string Name
{
get => _nameField;
set
{
if (!EqualityComparer<string>.Default.Equals(_nameField, value))
{
_nameField = value;
NotifyPropertyChanged(nameof(Name));
}
}
}
How would I achive it?我将如何实现它? What would I have to do?我该怎么办? How can I let the attribute hook into the Build?如何让属性挂钩到构建中? As you can see I have no clues at all of the Build process, nor of Roslyn.如您所见,我对构建过程和 Roslyn 都一无所知。 But I want to get rid of superfluous MVVM boilerplate code and no longer spent too much time for dull repetitive typing....但我想摆脱多余的 MVVM 样板代码,不再花太多时间进行枯燥的重复输入......
Thx, Chris谢谢,克里斯
There's a Fody weaver for this, called PropertyChanged .为此有一个Fody编织器,称为PropertyChanged 。
Fody is a system for modifying your code at the end of the compile process. Fody 是一个用于在编译过程结束时修改代码的系统。 The PropertyChanged weaver automatically impements change notification for all properties in all classes that implement INotifyPropertyChanged
. PropertyChanged 编织器自动为实现INotifyPropertyChanged
的所有类中的所有属性执行更改通知。 It has a number of ways to control the generation using attributes, implementing methods, etc.它有多种使用属性、实现方法等来控制生成的方法。
The example from their GitHub project page starts like this:他们的 GitHub 项目页面中的示例如下所示:
public class Person : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName => $"{GivenNames} {FamilyName}";
}
The weaver interprets the above and generates code like this:编织器解释上述内容并生成如下代码:
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");
}
Of course you won't have access to that version, since it happens somewhere around the end of the compilation pass and your source is unaffected.当然,您将无法访问该版本,因为它发生在编译过程结束时的某个地方,并且您的源不受影响。 Debugging the code can be a little difficult.调试代码可能有点困难。
To help with that the PropertyChanged weaver looks for pre-implemented methods matching various rules and generates code to call those.为了帮助实现这一点,PropertyChanged 编织器会查找与各种规则匹配的预实现方法并生成代码来调用这些方法。 If you have an OnPropertyChanged
method in the class it'll call that instead of generating a boilerplate version.如果您在 class 中有OnPropertyChanged
方法,它将调用该方法而不是生成样板版本。 Or you can add an OnFamilyNameChanged
method to the class above and that will be called before the OnPropertyChanged
method.或者,您可以在上面的 class 中添加一个OnFamilyNameChanged
方法,该方法将在OnPropertyChanged
方法之前调用。
You can use Roslyn source generators for that: Source Generators Cookbook您可以为此使用 Roslyn 源代码生成器: Source Generators Cookbook
There's an INotifyPropertyChanged
example .有一个INotifyPropertyChanged
示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.