2011-12-22 10 views
5

Vorrei implementare il seguente suggerimento di CodeContracts:Posso usare SuppressMessage su un metodo 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) 

Ci si sente come dovrei essere in grado di utilizzare SupressMessage con l'attributo di destinazione per rendere questo accada. Tuttavia, poiché questo è un metodo di Framework, non sono sicuro.

//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.")] 

Come faccio a sopprimere a livello globale questo avvertimento, in modo da non dover basale o sopprimere tutte le avvertenze 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

c'è un motivo che non si sta usando 'Contract.Assume'? Troppi avvenimenti? – porges

+0

Abbiamo cercato di stare lontano dal contratto. Assume generalmente, ma sì, ci sono un bel po 'di eventi e continuiamo ad aggiungerne altri. –

+0

Suppongo che il problema sia che i vari modi per acquisire Expressions/MethodInfos non assicurano che il risultato non sia nullo. Hai preso in considerazione l'utilizzo di alcuni metodi di wrapper come quelli forniti in: http://social.msdn.microsoft.com/Forums/en-NZ/codecontracts/thread/d8e2c2ad-de37-42ef-a854-02052d821975? In questo modo hai solo bisogno di "Assumere" in un posto, quindi l'utilizzo di "Assume" è ridotto al minimo. – porges

risposta

3

Dopo ulteriori indagini con il ranomoro, sembra esserci un errore nei Contratti di codice.

La classe a cui si accede tramite n => n.Value ha una proprietà generica T Value. Se la classe viene modificata in una classe non generica (con object Value), l'avviso scompare. (Una classe generica con object Value fornisce anche l'avviso).

Naturalmente, questo non risponde alla domanda originale, ma non credo sia possibile farlo.

+0

Non deve essere, altrimenti qualcuno avrebbe già risposto. ;) –

-1

dare uno sguardo alla scheda Costruisci delle vostre proprietà del progetto. C'è un campo "Elimina avvisi".

/nowarn (C# Compiler Options)

+1

Questi non sono avvertimenti _compiler_, sono avvisi _code_appalto_. Per quanto posso dire, non hanno un numero - quindi non posso semplicemente chiamare/nowarn: 5275 –

+0

Ah, non ho prestato abbastanza attenzione! Questo è il prezzo che si paga per non dormire. – Amy

+0

Si prega di non postare collegamenti MSDN con numeri di versione, a meno che non intendiate puntare a una versione specifica della documentazione. Il problema è che le persone iniziano a cliccare sui link da quelle pagine e finiscono col catturare, per esempio, in .NET 2.0-land. –

0
  1. Aggiungi GlobalSuppressions.cs alla radice del progetto.

  2. Aggiungi la tua [modulo ...

  3. Sostituire il modulo di parola con il montaggio.

Funziona?

+0

Ho avuto grandi speranze, ma purtroppo non funziona. Ho rimosso anche l'ambito = "membro", nel caso in cui fosse importante. –

0

In realtà funziona. È possibile aggiungere un SupressMessageAttribute al metodo che contiene l'espressione. Basta non usare RequiresAtCall. Invece, utilizzare 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); 
} 

Lo svantaggio evidente è che si dovrà gesso il codice con questi ...

+0

Non è abbastanza pericoloso? Questo è tutto richiede che tu stia sopprimendo là. Speravo di sopprimere solo l'unico messaggio. –

+0

@ranomore: Sì, puoi anche sopprimere solo questo messaggio. Invece di 'Requires' devi usare' Requires-11-10' dove i numeri specificano la posizione esatta dell'avviso. Si ottengono questi numeri dai Contratti di codice quando si aggiunge quanto segue ai comandi aggiuntivi per il controllo statico nella pagina delle proprietà del progetto Contratti di codice: '-outputwarnmask'. Per ogni avviso verrà generato (nella finestra Output, non nell'elenco degli errori) un messaggio che fornisce l'attributo SupressMessage completo che è possibile utilizzare per sopprimere tale avviso specifico. –

+0

Non l'ho usato per le mie classi di mappatura NHibernate, perché ero troppo pigro :) –

Problemi correlati