2010-03-07 9 views
6

Recientemente comencé a experimentar con PostSharp y encontré un aspecto particularmente útil para automatizar la implementación de INotifyPropertyChanged. Puede ver el ejemplo here. La funcionalidad básica es excelente (se notificarán todas las propiedades), pero hay casos en los que es posible que desee suprimir la notificación.Suprimir PostSharp Multicast con el atributo

Por ejemplo, podría saber que una propiedad en particular se establece una vez en el constructor y nunca volverá a cambiar. Como tal, no hay necesidad de emitir el código para NotifyPropertyChanged. La sobrecarga es mínima cuando las clases no se instancian con frecuencia y puedo evitar el problema cambiando de una propiedad generada automáticamente a una propiedad con respaldo de campo y escribiendo en el campo. Sin embargo, a medida que aprenda esta nueva herramienta, sería útil saber si existe una forma de etiquetar una propiedad con un atributo para suprimir la generación de código. Me gustaría ser capaz de hacer algo como esto:

[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; 
    } 
} 

Respuesta

5

Se puede utilizar un MethodPointcut en lugar de un MulticastPointcut, es decir, utilizar LINQ-sobre-reflexión y el filtro contra PropertyInfo.IsDefined (el atributo).

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

Excelente, gracias. Esta es una herramienta muy poderosa y mi proyecto se siente significativamente más limpio sin todas las tediosas tuberías de INotifyPropertyChanged. –

0

FYI, he tenido algunos problemas con el ejemplo en la página web Sharpcrafters y tuvo que hacer el siguiente cambio:

/// <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; 

Creo que estaba introduciendo el miembro OnPropertyChanged, pero la importación antes de que tuviera posibilidad de ser creado Esto haría que OnPropertySet fallara porque this.OnPropertyChangedMethod era nulo.

3

Otro método fácil, utilice:

[NotifyPropertyChanged(AttributeExclude=true)] 

... para suprimir los atributos de un método en particular. Esto funciona incluso si hay un atributo global asociado a la clase (como en el ejemplo anterior).

Aquí es el código de ejemplo completo:

[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; 
    } 
} 

Una vez que añadir esta línea, PostSharp incluso actualizar la interfaz gráfica de usuario MSVS a quitar el subrayado indica qué atributos se adjunta al método. Por supuesto, si ejecuta el depurador, se saltará la ejecución de cualquier atributo en ese método en particular.

Cuestiones relacionadas