2012-03-01 21 views
15

Background: gestisco un gran soluzione. Ogni tanto le persone aggiungono un riferimento DLL a un progetto nella soluzione in cui dovrebbero aver aggiunto un riferimento al progetto. Voglio emettere un avvertimento in questo caso. Voglio farlo trovando tutti i riferimenti con 'bin \ debug' nel loro HintPath *. So che i riferimenti sono Articoli in ItemGroup, con i metadati "HintPath".Uso delle funzioni Voce su metadati valori

mi aspettavo qualcosa di simile al lavoro:

<Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)" 
     Condition="%(Reference.HintPath).IndexOf('bin\debug') != -1"/> 

Tuttavia, sembra che io non posso usare la funzione di stringa IndexOf così. Ho provato molte permutazioni di quanto sopra, senza successo.

  • Modifica: so che questo controllo non è a prova di tutto, ma voglio solo ridurre gli errori onesti.

risposta

18

Utilizzando MSBuild 4.0 Property Functions è possibile fare confronti tra stringhe:

<Target Name="AfterBuild"> 

    <Message Text="Checking reference... '%(Reference.HintPath)'" Importance="high" /> 

    <Warning Text="Reference %(Reference.Identity) should be a project reference. HintPath: %(Reference.HintPath)" 
      Condition="$([System.String]::new('%(Reference.HintPath)').Contains('\bin\$(Configuration)'))" /> 

</Target> 
+1

+1: Ero così interessato a ottenere una proprietà dai metadati dell'articolo, che non ho visto questa cosa ovvia. In realtà, dato il tuo bisogno specifico, questo sembra molto meglio. –

+0

Funziona per me. Vorrei poter fare una ricerca senza distinzione tra maiuscole e minuscole - IndexOf ('\ bin \ $ (Configuration)', StringComparison.OrdinalIgnoreCase) - ma MSBuild non sembra in grado di richiamare funzioni con sovraccarichi. – Jonathan

+0

+1 Quando stavo cercando di risolvere il problema da solo, ho pensato a questa idea, ma non mi ero reso conto di come istanziare l'oggetto stringa (in realtà, non sono molto fluente in C#). Grazie per la soluzione. –

2

Prima non è che la sintassi non è corretta per le funzioni di invocare, si avrebbe bisogno di essere:

%(Reference.HintPath.IndexOf(...))  # Note: not supported by MSBuild 

Tuttavia, le funzioni di proprietà in MSBuild sono not allowed sui metadati voce, in modo che non sta andando per aiutare neanche tu.

Che cosa si potrebbe ovviare a questo, invocando un obiettivo separato che è fondamentalmente chiamato per ogni articolo.

<Target Name="CheckProjectReferences"> 
    <MSBuild 
     Projects="$(MSBuildProjectFullPath)" 
     Properties="Identity=%(Reference.Identity);HintPath=%(Reference.HintPath)" 
     Targets="_Warn"/> 
    </Target> 

    <Target Name="_Warn"> 
    <Warning Text="Reference $(Identity) should be a project reference. HintPath: $(HintPath)" 
      Condition="$(HintPath.IndexOf('bin\debug')) != -1"/> 
    </Target> 

Francamente, non sono sicuro che sia sufficiente per cogliere tutte le "violazioni". Ad esempio, quanto sopra funzionerà solo per bin\debug, ma non per bin\Debug o altre varianti con involucro misto, che sono funzionalmente equivalenti. Per cercare per loro, avresti bisogno di chiamare il IndexOf(string, StringComparison) sovraccarico, ma solo facendo:

$(HintPath.IndexOf('bin\debug', System.StringComparison.OrdinalIgnoreCase)) 

Non funzionerà, perché la risoluzione di sovraccarico MSBuild vi verrà a prendere IndexOf(char, Int32) e vi darà questo errore:

MSB4184: The expression ""bin\debug".IndexOf(bin\debug, System.StringComparison.OrdinalIgnoreCase)" cannot be evaluated. String must be exactly one character long.

Quindi, è necessario convincere esso utilizzando il IndexOf(String, Int32, Int32, StringComparison) sovraccarico direttamente:

$(HintPath.IndexOf('bin\debug', 0, 9, System.StringComparison.OrdinalIgnoreCase)) 

potrebbe essere necessario controllare anche per la bin\Release o altre varianti. Non sono sicuro che quello sia il modo migliore per capire un riferimento dovrebbe essere un riferimento al progetto, ma se si conosce (e per un certo controllo esteso) il proprio ambiente potrebbe essere fattibile.

+0

Questo sembra funzionare, anche se ho bisogno di un requisito ulteriore per arbitri senza HintPath. Tuttavia, invocare msbuild per ogni riferimento è lento: la mia soluzione è rallentata da 2 secondi a 34 secondi! Se non c'è modo di farlo nella stessa istanza di msbuild, non ne vale la pena per me. – Jonathan

+0

@Jonathan Stavo cercando, cercando di trovare un modo per farlo nella stessa istanza MSBuild, ma non ho trovato nessuno (a meno di scrivere la tua attività forse). –

0

@ Christian.K è proprio nella sua analisi. Un'altra soluzione potrebbe essere quella di forzare il sovraccarico di tipo stringa utilizzando &quot; per le citazioni:

<Warning 
    Text="..." 
    Condition="$(HintPath.IndexOf(&quot;bin\debug&quot;, System.StringComparison.OrdinalIgnoreCase)) != -1" /> 
Problemi correlati