2014-08-29 5 views
27

Ich mache eine Erweiterung zu Visual Studio. Innerhalb des Codes verwende ich Code-Verträge, um Assertions und Checks zu machen. Ich setze die Warnoption auf hoch.Wie kann ich Code Contracts veranlassen, eine bestimmte Assembly-Referenz zu ignorieren?

Ich möchte diese Warnstufe beibehalten und dabei alle Prüfungen ignorieren, die an EnvDTE-Referenzen vorgenommen werden.

Betrachten Sie das folgende Codebeispiel:

public static string GetAbsoluteOutputFolder(EnvDTE.Project project) 
{ 
    if (project == null) throw new ArgumentNullException("project"); 

    var path = 
     project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString(); 
    //... 
} 

Mit meiner aktuellen Einstellungen, CC würde mir verlangen die folgenden Prüfungen hinzufügen, bevor die path Variablen zugewiesen:

Contract.Assume(project.ConfigurationManager != null); 
Contract.Assume(project.ConfigurationManager.ActiveConfiguration != null); 
Contract.Assume(project.ConfigurationManager.ActiveConfiguration.Properties != null); 

Deshalb, was Ich mag würde Um dies zu tun, muss CC angewiesen werden, EnvDTE zu "vertrauen" und diese Typen und ihre Eigenschaften zu ignorieren.

Ich dachte, die CC-Option "Sei optimistisch für externe API" diente genau diesem Zweck; stellt sich heraus, dass es nicht geht.

Gibt es eine Möglichkeit, es so zu verhalten, wie ich will , die keine untere Warnstufe benötigen würde?

BEARBEITEN: Ich möchte eine Lösung, die auf Projektebene arbeiten würde und die noch "regelmäßige" Prüfungen ermöglichen würde.

+1

Wenn ich ich wäre, würde ich nur die Checks hinzufügen, die Sie weglassen möchten.Wenn Ihr Code wegen einer Nullreferenz in EnvDTE.Project explodiert, sollten Sie genau wissen, wo das Problem liegt, anstatt zu versuchen, den Nullpunkt zu erraten. –

+0

@MikeBurdick Die Sache ist, dass einige dieser Eigenschaften sehr wahrscheinlich nie null sind. Da diese Baugruppe jedoch nicht mit Verträgen kompiliert wurde, kann der Motor nichts sagen. Daher behandelt es diese Eigenschaften wie Eigenschaften ohne Verträge und erzwingt die sinnlose Überprüfung derselben Eigenschaft immer wieder. Wenn es eine globale, do-it-once Möglichkeit gäbe, die '' Configuration.Properties'' zum Beispiel zu erzwingen, die niemals null zurückgibt, würde ich sie gerne benutzen, aber es gibt sie nicht. Also, IMHO wäre das kleinere Übel, CC zu sagen, dass es einfach jeden Code ignorieren soll, der zu dieser bestimmten Assembly gehört. – Crono

Antwort

4

Kann nicht eine detaillierte Lösung zur Verfügung stellen, aber dies sollte entweder mit dem Baseline-Feature oder System.Diagnostics.CodeAnalysis.SuppressMessage auf Baugruppenebene lösbar sein:

[assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Contracts", "Whatever")] 

Sie verwenden, um das „Target“ Eigentum von die SuppressMessageAttribute nur die Nachricht zu bestimmten Typen/Schulen/Namespaces zu ignorieren:

[SupressMessage("Microsoft.Contracts", "CC1055", Scope="Member", Target="YouNamespace.EnvDTE.Project"] 

Beachten Sie, dass die Parameter i verwendet werden, sind nur eine gute Wette, ich wurde hat die richtige Scope, Meldungs ​​herauszufinden und Ziel selbst:) Auf einer Nebenbemerkung, ich denke, das Attribut ist bedingt ("CODE_ANALYSIS").

Die offizielle vorgeschlagene Lösung für dieses Problem ist, eine Art Wrapper zu erstellen, in Ihrem Fall wahrscheinlich ein Repository, das Ihre EnvDTE.Project-Objekte erstellen oder enthalten würde. Dann können Sie dort die erforderlichen Contract.Ensures hinzufügen.

+0

Wie kann ich eine Warnung auf Baugruppenebene platzieren, wenn ich den Code für diese Baugruppe nicht besitze? – Crono

+1

@Crono: Sie können Nachrichten in externen Bibliotheken unterdrücken, indem Sie die "Target" Eigenschaft des SuppressMessageAttribute verwenden, ich füge das zur Antwort hinzu. – Mecaveli

0

Haben Sie versucht, etwas mit: [assembly: Contracts.ContractVerification(false)] auf Assembly-Ebene?

Sie sollten in der Lage sein, es zu tun, dynamisch: https://msdn.microsoft.com/en-us/library/bb458043.aspx

hoffte, das hilft,

+1

Wenn ich dieses Attribut richtig verstehe, wird nur die Vertragsüberprüfung in dieser Baugruppe verhindert. Was OP möchte, ist, alle Warnungen zu ignorieren, die mit der Assembly erstellt wurden. –

1

Ich glaube nicht, es ist möglich, das Problem zu lösen, aber da C# 6.0 gibt es eine Abhilfe, die zumindest das erleichtert Schmerz ein bisschen:

Statt

Contract.Assume(project.ConfigurationManager != null); 
Contract.Assume(project.ConfigurationManager.ActiveConfiguration != null); 
Contract.Assume(project.ConfigurationManager.ActiveConfiguration.Properties != null); 

können Sie jetzt schreiben

Contract.Assume(project.ConfigurationManager?.ActiveConfiguration?.Properties != null); 
Verwandte Themen