2011-12-22 16 views
5

me gustaría poner en práctica la siguiente sugerencia de CodeContracts:¿Puedo usar SuppressMessage en un método de framework?

CodeContracts: MyModule: Method MyModule.MyClass.MyMethod: 
To mask *all* warnings issued like the precondition add the attribute: 

[SuppressMessage("Microsoft.Contracts", "RequiresAtCall-propertyAccessor != null")] 

to the method 

System.Linq.Expressions.Expression.Property(System.Linq.Expressions.Expression,System.Reflection.MethodInfo) 

Se siente como que debería ser capaz de utilizar SupressMessage con el atributo de destino para que esto suceda. Sin embargo, como este es un método Framework, no estoy seguro.

//doesn't work 
[module: SuppressMessage("Microsoft.Contracts", "RequiresAtCall-propertyAccessor != null", Scope = "Member", Target = "System.Linq.Expressions.Expression.Property(System.Linq.Expressions.Expression,System.Reflection.MethodInfo)", Justification = "This isn't covered by Linq Contracts yet.")] 

¿Cómo puedo suprimir esta advertencia a nivel mundial, por lo que no tienen a la línea base o suprimir todas las advertencias callsite?

EDIT: The specific usage that requires this measure is: 

void mymethod() 
{ 
    var myObserver = new PropertyObserver<MyViewModel>(); 
    //this line throws the error, within the n => n.Value expression 
    myObserver.RegisterHandler(n => n.Value, OnValueChanged); 
} 

public class PropertyObserver<TPropertySource> where TPropertySource : INotifyPropertyChanged 
{ 
    public PropertyObserver<TPropertySource> RegisterHandler(
     Expression<Func<TPropertySource, object>> expression, 
     Action<TPropertySource> handler) 
    { 
     //what this does is irrelevant; the violation occurs in the method call 
    } 
} 

//n => n.Value decompiles to the following 
public static MemberExpression Property (Expression expression, MethodInfo propertyAccessor) 
{ 
    //and this line is the message I want to suppress, but it's in the .NET framework. 
    ContractUtils.RequiresNotNull(propertyAccessor, "propertyAccessor"); 
    ValidateMethodInfo(propertyAccessor); 
    return Property (expression, GetProperty(propertyAccessor)); 
} 
+0

¿Existe una razón por la que usted no está usando 'Contract.Assume'? ¿Demasiadas ocurrencias? – porges

+0

Hemos intentado evitar el contrato. En general, sí, pero sí, hay bastantes casos y seguimos agregando más. –

+0

Supongo que el problema es que las diversas formas de adquirir Expressions/MethodInfos no garantizan que el resultado no sea nulo. ¿Ha considerado utilizar algunos métodos de envoltura como los que figuran en: http://social.msdn.microsoft.com/Forums/en-NZ/codecontracts/thread/d8e2c2ad-de37-42ef-a854-02052d821975? De esta forma solo necesitas 'Assume' en un solo lugar, por lo que el uso de' Assume' se minimiza. – porges

Respuesta

3

Después de algunas investigaciones más con ranomore, parece que hay un error en los Contratos de Código.

La clase a la que se accede a través de n => n.Value tiene una propiedad genérica T Value. Si la clase se cambia a una clase no genérica (con object Value), la advertencia desaparece. (Una clase genérica con object Value también da la advertencia).

Por supuesto, esto no responde a la pregunta original, pero no creo que sea posible hacerlo.

+0

No debe ser así, de lo contrario, alguien ya lo habría respondido. ;) –

-1

Eche un vistazo a la pestaña Construir de las propiedades de su proyecto. Hay un campo "Suprimir advertencias".

/nowarn (C# Compiler Options)

+1

Estas no son _compiler_ advertencias, son _code contract_ warnings. Por lo que puedo decir, no tienen un número, así que no puedo simplemente llamar/a Nowarn: 5275 –

+0

¡Ah, no presté suficiente atención! Este es el precio que paga por no dormir. – Amy

+0

No publique enlaces de MSDN con números de versión en ellos, a menos que desee apuntar a una versión específica de la documentación. El problema es que las personas comienzan a hacer clic en los enlaces de esas páginas y terminan atrapados, por ejemplo, en .NET 2.0-land. –

0
  1. Añadir GlobalSuppressions.cs a raíz del proyecto.

  2. Haz tu [... módulo de

  3. sustituir el módulo de palabra con el montaje.

¿Eso funciona?

+0

Tenía muchas esperanzas, pero, por desgracia, no funciona. También eliminé el Scope = "Member", por si importaba. –

0

Realmente funciona. Puede agregar SupressMessageAttribute al método que contiene la expresión. Simplemente no use RequiresAtCall. En su lugar, utilice Requires:

[SuppressMessage("Microsoft.Contracts", "Requires", 
       Justification = "Bug in static checker")] 
public void Override(AutoMapping<Bookings> mapping) 
{ 
    Contract.Assume(mapping != null); 

    mapping.Id(x => x.Id); 
} 

La desventaja obvia es que usted tendrá que revoque su código con estos ...

+0

¿No es eso bastante peligroso? Eso es todo lo que requiere que estés suprimiendo allí. Esperaba suprimir solo el mensaje. –

+0

@ranomore: Sí, también puedes suprimir solo este mensaje. En lugar de 'Requiere', debe usar' Requires-11-10' donde los números especifican la ubicación exacta de la advertencia. Obtiene esos números de Contratos de código cuando agrega lo siguiente a los comandos adicionales para el verificador estático en la página de propiedades del proyecto Contratos de código: '-outputwarnmask'. Para cada advertencia, mostrará (en la ventana Salida, no en la lista de errores) un mensaje que le proporciona el atributo SupressMessage completo que puede usar para suprimir esa advertencia específica. –

+0

No usé esto para mis clases de mapeo de NHibernate, porque era demasiado flojo :) –

Cuestiones relacionadas