簡體   English   中英

屬性掛鈎 MSBuild/Roslyn

[英]Attribute hooking 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 編織器會查找與各種規則匹配的預實現方法並生成代碼來調用這些方法。 如果您在 class 中有OnPropertyChanged方法,它將調用該方法而不是生成樣板版本。 或者,您可以在上面的 class 中添加一個OnFamilyNameChanged方法,該方法將在OnPropertyChanged方法之前調用。

您可以為此使用 Roslyn 源代碼生成器: Source Generators Cookbook

有一個INotifyPropertyChanged示例

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM