2010-03-07 23 views
6

Gần đây tôi đã bắt đầu thử nghiệm với PostSharp và tôi đã tìm thấy một khía cạnh đặc biệt hữu ích để tự động thực hiện INotifyPropertyChanged. Bạn có thể xem ví dụ here. Các chức năng cơ bản là tuyệt vời (tất cả các thuộc tính sẽ được thông báo), nhưng có những trường hợp mà tôi có thể muốn ngăn chặn thông báo.Ức chế PostSharp Multicast với thuộc tính

Ví dụ: tôi có thể biết rằng một thuộc tính cụ thể được đặt một lần trong hàm tạo và sẽ không bao giờ thay đổi nữa. Như vậy, không cần phải phát ra mã cho NotifyPropertyChanged. Chi phí trên là tối thiểu khi các lớp không được khởi tạo thường xuyên và tôi có thể ngăn chặn vấn đề bằng cách chuyển từ một thuộc tính được tạo tự động sang một thuộc tính do trường hậu thuẫn và ghi vào trường. Tuy nhiên, khi tôi đang học công cụ mới này, sẽ rất hữu ích nếu biết có cách để gắn thẻ thuộc tính với thuộc tính để chặn tạo mã. Tôi muốn để có thể làm điều gì đó như thế này:

[NotifyPropertyChanged] 
public class MyClass 
{ 
    public double SomeValue { get; set; } 

    public double ModifiedValue { get; private set; } 

    [SuppressNotify] 
    public double OnlySetOnce { get; private set; } 

    public MyClass() 
    { 
     OnlySetOnce = 1.0; 
    } 
} 

Trả lời

5

Bạn có thể sử dụng một MethodPointcut thay vì một MulticastPointcut, ví dụ: sử dụng LINQ-over-Reflection và bộ lọc chống PropertyInfo.IsDefined (thuộc tính của bạn).

private IEnumerable<PropertyInfo> SelectProperties(Type type) 
    { 
     const BindingFlags bindingFlags = BindingFlags.Instance | 
      BindingFlags.DeclaredOnly 
              | BindingFlags.Public; 

     return from property 
        in type.GetProperties(bindingFlags) 
       where property.CanWrite && 
        !property.IsDefined(typeof(SuppressNotify)) 
       select property; 
    } 

    [OnLocationSetValueAdvice, MethodPointcut("SelectProperties")] 
    public void OnSetValue(LocationInterceptionArgs args) 
    { 
     if (args.Value != args.GetCurrentValue()) 
     { 
      args.ProceedSetValue(); 

      this.OnPropertyChangedMethod.Invoke(null); 
     } 
    } 
+0

Tuyệt vời, cảm ơn bạn. Đây là một công cụ rất mạnh mẽ và dự án của tôi cảm thấy sạch hơn đáng kể mà không cần đến hệ thống ống nước INotifyPropertyChanged tẻ nhạt. –

0

FYI, tôi đã có một số vấn đề với ví dụ trên trang web Sharpcrafters và phải thực hiện thay đổi sau đây:

/// <summary> 
    /// Field bound at runtime to a delegate of the method <c>OnPropertyChanged</c>. 
    /// </summary> 
    [ImportMember("OnPropertyChanged", IsRequired = true, Order = ImportMemberOrder.AfterIntroductions)] 
    public Action<string> OnPropertyChangedMethod; 

tôi nghĩ rằng nó đã được giới thiệu các thành viên OnPropertyChanged, nhưng nhập khẩu trước khi nó đã có một cơ hội được tạo ra. Điều này sẽ khiến cho OnPropertySet thất bại vì this.OnPropertyChangedMethod là null.

3

Một phương pháp dễ dàng, sử dụng:

[NotifyPropertyChanged(AttributeExclude=true)] 

... để ngăn chặn các thuộc tính cho một phương pháp cụ thể. Điều này làm việc ngay cả khi có một thuộc tính chung được gắn với lớp (như trong ví dụ trên).

Đây là đoạn mã ví dụ đầy đủ:

[NotifyPropertyChanged] 
public class MyClass 
{ 
    public double SomeValue { get; set; } 

    public double ModifiedValue { get; private set; } 

    [NotifyPropertyChanged(AttributeExclude=True)] 
    public double OnlySetOnce { get; private set; } 

    public MyClass() 
    { 
     OnlySetOnce = 1.0; 
    } 
} 

Khi bạn thêm dòng này, PostSharp thậm chí sẽ cập nhật các GUI MSVS để loại bỏ các gạch dưới chỉ ra mà thuộc tính được gắn vào phương pháp này. Tất nhiên, nếu bạn chạy trình gỡ rối, nó sẽ bỏ qua việc thực hiện bất kỳ thuộc tính nào trên phương thức cụ thể đó.

Các vấn đề liên quan