Share via



Ottobre 2015

Volume 30 Numero 10

Il presente articolo è stato tradotto automaticamente.

Analisi del codice - Compilare e distribuire le librerie con l'analisi del codice Roslyn integrata in NuGet

Da Alessandro Del Del

La piattaforma del compilatore di Microsoft .NET (denominata anche la base di codice "Roslyn") offre i compilatori c# e Visual Basic Apri origine che espongono, ad esempio, è possibile utilizzare per la creazione di regole di analisi live che si integrano nell'editor di codice di Visual Studio 2015 l'analisi del codice RTF API. Con la piattaforma del compilatore .NET, è possibile scrivere refactoring e analizzatori di codice personalizzato, specifico di dominio in modo che Visual Studio è possibile rilevare problemi nel codice durante la digitazione, avvisi e messaggi di errore di reporting. Un grande vantaggio della piattaforma del compilatore .NET è che è possibile aggregare analizzatori di codice con l'API. Ad esempio, se si creano librerie o controlli utente riutilizzabili, è possibile spedire analizzatori con le librerie e offrire agli sviluppatori una migliore esperienza di codifica.

In questo articolo spiegherò come creare un bundle di librerie e analizzatori in pacchetti NuGet per la distribuzione in linea, che mostra come è possibile offrire analisi del codice Roslyn integrata per l'API. È necessario che avere almeno una conoscenza di base sui concetti di piattaforma del compilatore .NET e sulla scrittura di un analizzatore del codice. Questi argomenti sono stati illustrati negli ultimi articoli di MSDN Magazine da Alex Turner: "In c# e Visual Basic: Consente di scrivere un analizzatore del codice attivo per l'API Roslyn"(msdn.microsoft.com/magazine/dn879356) e" c#: aggiunta di una correzione del codice per l'analizzatore di Roslyn "(msdn.microsoft.com/magazine/dn904670), che si è consigliabile leggere prima di andare qui.

Preparazione di una libreria di esempio per simulare le API personalizzate

La prima cosa è una libreria di classi che simula un'API personalizzata. La libreria di esempio per l'articolo espone un metodo pubblico semplice che recupera informazioni comuni da un feed RSS, che restituisce un insieme di elementi feed. In Visual Studio 2015, creare una nuova libreria di classi portabile chiamato FeedLibrary con c# o Visual Basic e assicurarsi che la destinazione minima è Windows 8.1, Windows Phone 8.1 e Microsoft .NET Framework 4.5.1. Con questa destinazione, la libreria può sfruttare i vantaggi del modello Async/Await senza requisiti aggiuntivi.

Rinominare il file Class1. vb o Class1. cs generato in FeedItem.vb/.cs. Il codice c# per questa classe è in Figura 1 e il codice Visual Basic in Figura 2.

Figura 1 implementa una classe per recuperare gli elementi comuni di un RSS Feed in c#

using System.Net.Http;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace FeedLibrary
{
  // Represent a single content in the RSS feed
  public class FeedItem
  {
    // Properties representing information,
    // which is common to any RSS feed
    public string Title { get; set; }
    public string Author { get; set; }
    public string Description { get; set; }
    public DateTimeOffset PubDate { get; set; }
    public Uri Link { get; set; }
    // Return a collection of FeedItem objects from a RSS feed
    public static async Task<IEnumerable<FeedItem>> ParseFeedAsync(
      string feedUrl)
    {
      var client = new HttpClient();
      // Download the feed content as a string
      var result = await client.GetStringAsync(new Uri(feedUrl));
      // If no result, throw an exception
      if (result == null)
      {
        throw new InvalidOperationException(
          "The specified URL returned a null result");
      }
      else
      {
        // LINQ to XML: Convert the returned string into an XDocument object
        var doc = XDocument.Parse(result);
        var dc = XNamespace.Get("http://purl.org/dc/elements/1.1/");
        // Execute a LINQ query over the XML document
        // and return a collection of FeedItem objects
        var query = (from entry in doc.Descendants("item")
                     select new FeedItem
                     {
                         Title = entry.Element("title").Value,
                         Link = new Uri(entry.Element("link").Value),
                         Author = entry.Element(dc + "creator").Value,
                         Description = entry.Element("description").Value,
                         PubDate = DateTimeOffset.Parse(
                           entry.Element("pubDate").Value,
                     System.Globalization.CultureInfo.InvariantCulture)
                     });
        return query;
      }
    }
  }
}

Figura 2 implementazione di una classe per recuperare gli elementi comuni da un Feed RSS in Visual Basic

Imports System.Net.Http
Imports <xmlns:dc="http://purl.org/dc/elements/1.1/">
'Represent a single content in the RSS feed
Public Class FeedItem
  'Properties representing information
  'which is common to any RSS feed
  Public Property Title As String = String.Empty
  Public Property Author As String = String.Empty
  Public Property Description As String = String.Empty
  Public Property PubDate As DateTimeOffset
  Public Property Link As Uri
  'Return a collection of FeedItem objects from a RSS feed
  Public Shared Async Function ParseFeedAsync(feedUrl As String) As _
    Task(Of IEnumerable(Of FeedItem))
    Dim client As New HttpClient
    'Download the feed content as a string
    Dim result = Await client.GetStringAsync(New Uri(feedUrl, UriKind.Absolute))
    'If no result, throw an exception
    If result Is Nothing Then
       Throw New InvalidOperationException(
         "The specified URL returned a null result")
    Else
      'LINQ to XML: Convert the returned string
      'into an XDocument object
      Dim document = XDocument.Parse(result)
      'Execute a LINQ query over the XML document
      'and return a collection of FeedItem objects
      Dim query = From item In document...<item>
                  Select New FeedItem With {
                  .Title = item.<title>.Value,
                  .Author = item.<dc:creator>.Value,
                  .Description = item.<description>.Value,
                  .PubDate = DateTimeOffset.Parse(item.<pubDate>.Value),
                  .Link = New Uri(item.<link>.Value)}
      Return query
    End If
  End Function
End Class

Il codice è molto semplice: Scarica il diffuso URL del feed RSS, viene creata un'istanza della classe FeedItem per ogni elemento del feed contenuto dall'oggetto specificato e infine restituisce una nuova raccolta di elementi. Per utilizzare la libreria, è sufficiente richiamare il metodo statico ParseFeedAsyncAsync per c#, come indicato di seguito:

// Replace the argument with a valid URL
var items = await FeedItem.ParseFeedAsyncAsync("http://sampleurl.com/rss");

E per Visual Basic simile al seguente:

'Replace the argument with a valid URL
Dim items = Await FeedItem.ParseFeedAsyncAsync("http://sampleurl.com/rss")

Questa chiamata restituisce un oggetto IEnumerable < FeedItem >, che è quindi possibile utilizzare in base alle esigenze. Selezionare la configurazione di rilascio e compilare il progetto. a questo punto, 2015 di Visual Studio genera una libreria denominata FeedLibrary.dll, che verrà utilizzato in un secondo momento.

Scrittura di un analizzatore Roslyn

Il passaggio successivo consiste nel creare un analizzatore Roslyn che fornisce le regole di analisi live specifico di dominio per le API personalizzate. L'analizzatore rileverà se l'URL fornito come argomento del metodo ParseFeedAsyncAsync è corretto, utilizzando il metodo Uri.IsWellFormedUriString. in caso contrario, l'analizzatore verrà segnalato un avviso durante la digitazione. Naturalmente, esistono una vasta gamma di modi per rilevare se un URL non valido, ma utilizzare questa opzione per ragioni di semplicità. Inoltre, per gli stessi motivi, l'analizzatore fornirà live report avvisi di analisi, ma non offrirà le correzioni del codice, che viene lasciata all'utente come un esercizio. Detto questo, attenersi alla seguente procedura:

  1. In Esplora soluzioni, il nome della soluzione fare clic e scegliere Aggiungi | Nuovo progetto.
  2. Nel nodo di estendibilità dell'elenco di modelli di progetto, selezionare Analyzer con codice di correzione (NuGet + VSIX). Si noti che il nodo Extensibility non viene visualizzata per impostazione predefinita. È necessario innanzitutto scaricare il SDK di piattaforma del compilatore .NET per recuperare l'analizzatore con codice correggere progetti di modello. Analizzatori di ricerca nella finestra di dialogo Nuovo progetto e si vedrà il progetto di modello per scaricare questo SDK.
  3. Chiamare il nuovo analizzatore FeedLibraryAnalyzer e fare clic su OK.
  4. Quando il nuovo progetto è pronto, rimuovere il file CodeFixProvider.cs (o vb).

Nel file DiagnosticAnalyzer.cs (o vb), la prima cosa da fare è fornire stringhe che identificano l'analizzatore dell'esperienza di codifica. Per mantenere l'implementazione dell'analizzatore di più semplice, nell'esempio corrente utilizzare stringhe regolari anziché l'oggetto LocalizableString e file di risorse, presupponendo che l'analizzatore non dovrà essere localizzate. Riscrivere DiagnosticId, titolo, messaggio, descrizione e categoria per c#, come indicato di seguito:

public const string DiagnosticId = "RSS001";
internal static readonly string Title = "RSS URL analysis";
internal static readonly string MessageFormat = "URL is invalid";
internal static readonly string Description =
  "Provides live analysis for the FeedLibrary APIs";
internal const string Category = "Syntax";

E per Visual Basic, come indicato di seguito:

Public Const DiagnosticId = "RSS001"
Friend Shared ReadOnly Title As String = "RSS URL analysis"
Friend Shared ReadOnly MessageFormat As String = "URL is invalid"
Friend Shared ReadOnly Description As String =
  "Provides live analysis for the FeedLibrary APIs"
Friend Const Category = "Syntax"

Non modificare la gravità di diagnostica, che costituisce l'avviso per impostazione predefinita, una scelta appropriata per l'esempio corrente. A questo punto è il momento di concentrarsi sulla logica di analisi. L'analizzatore deve controllare se il codice richiama un metodo denominato ParseFeedAsync. In tal caso, l'analizzatore controllerà quindi se l'URL fornito è ben formato. Con l'aiuto del Visualizzatore di sintassi, si può vedere nella Figura 3 come una chiamata del metodo ParseFeedAsync è rappresentata da un InvocationExpression, il mapping a un oggetto di tipo InvocationExpressionSyntax.

Il Visualizzatore di sintassi consente di individuare la rappresentazione del nodo di sintassi
Figura 3 il Visualizzatore di sintassi consente di individuare la rappresentazione del nodo di sintassi

Pertanto l'analizzatore si concentra solo sugli oggetti di tipo InvocationExpressionSyntax; Quando ne trova uno, viene convertita l'espressione associata in un oggetto di tipo MemberAccessExpressionSyntax, che contiene informazioni su una chiamata al metodo. Se la conversione ha esito positivo, l'analizzatore verifica se il metodo ParseFeedAsync, quindi recupera il primo argomento e consente di eseguire analisi diretta al relativo valore. Questa operazione viene eseguita da un nuovo metodo, denominato AnalyzeMethod, che opera a livello di SyntaxNode e viene rappresentato in Figura 4 per c# e Figura 5 per Visual Basic.

Figura 4 il rilevamento di problemi in base all'argomento ParseFeedAsync in c#

private static void AnalyzeMethodInvocation(SyntaxNodeAnalysisContext context)
{
  // Convert the current syntax node into an InvocationExpressionSyntax,
  // which represents a method call
  var invocationExpr = (InvocationExpressionSyntax)context.Node;
  // Convert the associated expression into a MemberAccessExpressionSyntax,
  // which represents a method's information
  // If the expression is not a MemberAccessExpressionSyntax, return
  if (!(invocationExpr.Expression is MemberAccessExpressionSyntax))
  {
    return;
  }
  var memberAccessExpr = (MemberAccessExpressionSyntax)invocationExpr.Expression;
  // If the method name is not ParseFeedAsync, return
  if (memberAccessExpr?.Name.ToString() != "ParseFeedAsync") { return; }
  // If the method name is ParseFeedAsync, check for the symbol
  // info and see if the return type matches
  var memberSymbol = context.SemanticModel.
                     GetSymbolInfo(memberAccessExpr).
                     Symbol as IMethodSymbol;
  if (memberSymbol == null) { return; }
  var result = memberSymbol.ToString();
  if (memberSymbol?.ReturnType.ToString() !=
  "System.Threading.Tasks.Task<
    System.Collections.Generic.IEnumerable<FeedLibrary.FeedItem>>")
  {
      return;
  }
  // Check if the method call has the required argument number
  var argumentList = invocationExpr.ArgumentList;
  if (argumentList?.Arguments.Count != 1) {
      return; }
  // Convert the expression for the first method argument into
  // a LiteralExpressionSyntax. If null, return
  var urlLiteral = (LiteralExpressionSyntax)invocationExpr.ArgumentList.
      Arguments[0].Expression;
  if (urlLiteral == null) { return; }
  // Convert the actual value for the method argument into string
  // If null, return
  var urlLiteralOpt = context.SemanticModel.GetConstantValue(urlLiteral);
  var urlValue = (string)urlLiteralOpt.Value;
  if (urlValue == null) { return; }
  // If the URL is not well-formed, create a diagnostic
  if (Uri.IsWellFormedUriString(urlValue, UriKind.Absolute) == false)
  {
    var diagn = Diagnostic.Create(Rule, urlLiteral.GetLocation(),
      "The specified parameter Is Not a valid RSS feed");
    context.ReportDiagnostic(diagn);
  }
}

Figura 5 individuazione di problemi in base all'argomento ParseFeedAsync in Visual Basic

Private Sub Shared AnalyzeMethodInvocation(context As SyntaxNodeAnalysisContext)
  'Convert the current syntax node into an InvocationExpressionSyntax
  'which represents a method call
  Dim invocationExpr = CType(context.Node, InvocationExpressionSyntax)
  'Convert the associated expression into a MemberAccessExpressionSyntax
  'which represents a method's information
  'If the expression Is Not a MemberAccessExpressionSyntax, return
  If TypeOf invocationExpr.Expression IsNot MemberAccessExpressionSyntax Then Return
  Dim memberAccessExpr = DirectCast(invocationExpr.Expression,
    MemberAccessExpressionSyntax)
  'If the method name Is Not ParseFeedAsync, return
  If memberAccessExpr?.Name.ToString <> "ParseFeedAsync" Then Return
  'If the method name is ParseFeedAsync, check for the symbol info
  'and see if the return type matches
  Dim memberSymbol = TryCast(context.SemanticModel.
      GetSymbolInfo(memberAccessExpr).Symbol, IMethodSymbol)
  If memberSymbol Is Nothing Then Return
  Dim result = memberSymbol.ToString
  If Not memberSymbol?.ReturnType.ToString =
    "System.Threading.Tasks.Task(Of System.Collections.Generic.IEnumerable(
    Of FeedLibrary.FeedItem))"
    Then Return
  'Check if the method call has the required argument number
  Dim argumentList = invocationExpr.ArgumentList
  If argumentList?.Arguments.Count <> 1 Then Return
  'Convert the expression for the first method argument into
  'a LiteralExpressionSyntax. If null, return
  Dim urlLiteral =
    DirectCast(invocationExpr.ArgumentList.Arguments(0).GetExpression,
      LiteralExpressionSyntax)
  If urlLiteral Is Nothing Then Return
  'Convert the actual value for the method argument into string
  'If null, return
  Dim urlLiteralOpt = context.SemanticModel.GetConstantValue(urlLiteral)
  Dim urlValue = DirectCast(urlLiteralOpt.Value, String)
  If urlValue Is Nothing Then Return
  'If the URL Is Not well-formed, create a diagnostic
  If Uri.IsWellFormedUriString(urlValue, UriKind.Absolute) = False Then
     Dim diagn = Diagnostic.Create(Rule, urlLiteral.GetLocation,
       "The specified parameter Is Not a valid RSS feed")
     context.ReportDiagnostic(diagn)
  End If
End Sub

A questo punto, è necessario modificare il metodo Initialize per chiamare il metodo AnalyzeMethodInvocation appena aggiunto, come illustrato nella Figura 6 per c# e Figura 7 per Visual Basic.

Figura 6 modifica il metodo Initialize in c#

public override void Initialize(AnalysisContext context)
{
  // Register an action when compilation starts
  context.
    RegisterCompilationStartAction((CompilationStartAnalysisContext ctx) =>
  {
    // Detect if the type metadata
    // exists in the compilation context
    var myLibraryType =
    ctx.Compilation.
    GetTypeByMetadataName("FeedLibrary.FeedItem");
    // If not, return
    if (myLibraryType == null)
        return;
    // Register an action against an InvocationExpression
    ctx.RegisterSyntaxNodeAction(AnalyzeMethodInvocation,
      SyntaxKind.InvocationExpression);
  });
}

Figura 7 modifica il metodo Initialize in Visual Basic

Public Overrides Sub Initialize(context As AnalysisContext)
  ' Register an action when compilation starts
  context.
    RegisterCompilationStartAction
    (Sub(ctx As CompilationStartAnalysisContext)
      'Detect if the type metadata
      'exists in the compilation context
      Dim myLibraryType =
        ctx.Compilation.
          GetTypeByMetadataName("FeedLibrary.FeedItem")
        'If not, return
        '(no reference to the library)
        If myLibraryType Is Nothing
Then Return
        'Register an action against
        'an InvocationExpression
        ctx.RegisterSyntaxNodeAction(
          AddressOf AnalyzeMethodInvocation,
          SyntaxKind.InvocationExpression)
     End Sub)
End Sub

Si noti come il codice controlla innanzitutto l'esistenza di un riferimento alla libreria del progetto richiamando il metodo Compilation.GetTypeMetadataName, il cui argomento è il nome del tipo che deve essere presente nel contesto corrente per assicurarsi che sia stato aggiunto un riferimento. Se questa chiamata restituisce null, significa che il tipo non esiste e, pertanto, non è stato aggiunto alcun riferimento alla libreria. Pertanto, non è necessario registrare un'azione di analisi del codice, migliorando le prestazioni dell'analizzatore. Se ora si preme F5 per testare l'analizzatore nell'istanza sperimentale di Visual Studio 2015 e creare un nuovo progetto con un riferimento alla libreria FeedLibrary, sarà in grado di vedere come correttamente segnala un avviso ogni volta che è fornire un URL non valido, come illustrato nella Figura 8.

L'analizzatore segnala un avviso se l'URL non è corretto
Figura 8, l'analizzatore segnala un avviso se l'URL non è corretto

Finora avete creato codice correlato specifici del dominio e le API regole di analisi. Ora è possibile vedere come aggregare entrambi in un unico pacchetto NuGet.

Creazione di un pacchetto NuGet che include le API e analizzatori

Le regole di MSBuild per l'analizzatore di correggere codice modello di progetto consentono di automatizzare la generazione di un pacchetto NuGet che include l'analizzatore di compilate, è possibile condividere con altri sviluppatori mediante la pubblicazione in un repository NuGet. In pratica, ogni volta che si esegue il debug di un analizzatore premendo F5 o quando si compila il progetto analyzer, Visual Studio 2015 ricompila il file con estensione dll analyzer (FeedLibraryAnalyzer.dll nell'esempio corrente) e un pacchetto NuGet ridistribuibile che contiene l'analizzatore.

Il processo di compilazione genera inoltre un pacchetto VSIX che è possibile pubblicare in Visual Studio Gallery e che viene utilizzato anche per eseguire il debug analyzer all'interno dell'istanza sperimentale di Visual Studio 2015, ma questo esula dall'ambito di questo articolo e non viene trattato in questo argomento.

Se si desidera condividere una libreria con analisi Roslyn integrata, è necessario aggiungere la libreria per il pacchetto NuGet di Visual Studio 2015 generati quando si compila il progetto. Prima di procedere, è necessario acquisire maggiore sul modo in cui viene eseguito un pacchetto NuGet per un'analisi. In realtà, un pacchetto NuGet è un file ZIP con estensione .nupkg. Per questo motivo, è possibile esaminare il contenuto e la struttura di un pacchetto NuGet con uno strumento di archiviazione con estensione zip, come gli strumenti di cartella in Esplora risorse compressi, WinZip o WinRar facilmente. Di seguito è un riepilogo degli elementi più importanti in un pacchetto NuGet progettate per distribuire Analyzer:

  • .nuspec file: Questo file contiene i metadati del pacchetto e include le informazioni necessarie per la pubblicazione, nome del pacchetto, versione, descrizione, autore, URL di licenza e altro ancora. Il file .nuspec viene fornito nel pacchetto NuGet basato sul file Diagnostic.nuspec visualizzate in Esplora soluzioni all'interno del progetto analyzer. Viene modificato in Visual Studio 2015 Diagnostic.nuspec tra breve.
  • cartella Strumenti: Questa cartella contiene script di Windows PowerShell utilizzato da Visual Studio (Install.ps1) di installare e disinstallare (Uninstall.ps1) un analizzatore per un determinato progetto.
  • cartella Analyzer: Questa cartella contiene file con estensione dll analyzer organizzati in sottocartelle particolare. Librerie analyzer agnostico (che è destinato a tutte le lingue) si trovano in una sottocartella denominata dotnet. Analizzatori di c# di destinazione si trovano in una sottocartella denominata dotnet\cs, mentre analizzatori di Visual Basic di destinazione si trovano in una cartella denominata dotnet\vb. Vale la pena sottolineare che dotnet rappresenta il profilo di NuGet per .NET Core e supporta i tipi di progetti, ad esempio App Windows universali e progetti ASP.NET 5.

Un numero di elementi aggiuntivi può essere combinato in un pacchetto NuGet, ma qui mi concentrerò su un pacchetto tipico generato per un analizzatore di Roslyn, vengono trattati in modo che solo gli elementi necessari.

Le eventuali librerie che è possibile fare riferimento da un progetto di Visual Studio devono essere organizzate in una cartella denominata lib. Poiché le librerie può essere associato a piattaforme diverse, quali versioni diverse di .NET Framework, Windows Runtime, diverse versioni di Windows Phone o anche un subset portabile (incluse le librerie Xamarin), la cartella lib deve contenere una sottocartella per ogni piattaforma di destinazione e ciascuna sottocartella deve contenere una copia della libreria per la distribuzione. Il nome di ciascuna sottocartella deve corrispondere al nome di un profilo del cosiddetto che rappresenta una piattaforma specifica. Ad esempio, se si dispone di una libreria destinata a .NET Framework 4.5.1 e Windows 8.1, si avrebbe la struttura seguente, dove net451 è il nome del profilo per .NET Framework 4.5.1 e netcore451 è il nome del profilo per il Runtime di Windows in Windows 8.1:

lib\net451\mylib.dll
lib\netcore451\mylib.dll

Vale la pena citare il profilo uap10.0 che fa riferimento la piattaforma Windows universale (UWP) per creare applicazioni Windows 10. L'elenco completo dei profili supportati è disponibile nella documentazione di NuGet. La libreria di esempio creata in precedenza è una libreria portabile destinato a .NET Framework 4.5.1, Windows 8.1 e Windows Phone 8.1. Il nome del profilo per questo tipo di destinazione è portabile net451 + netcore451 + wpa81 e deve essere utilizzato per denominare la sottocartella che conterrà la libreria nel pacchetto NuGet. Non è necessario creare la sottocartella e copiare la libreria manualmente. è sufficiente modificare i metadati del pacchetto NuGet (il file Diagnostic.nuspec) all'interno di Visual Studio. Figura 9 Mostra i metadati aggiornati con le informazioni appropriate per la pubblicazione (id, titolo, autore, descrizione, licenze e così via) e un nuovo elemento di file nel nodo file che specifica il file di origine e la sottocartella di destinazione.

Figura 9 modifica i metadati del pacchetto NuGet

<?xml version="1.0"?>
<package xmlns="https://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
  <metadata>
    <id>RSSFeedLibrary</id>
    <version>1.0.0.0</version>
    <title>RSS Feed Library with Roslyn analysis</title>
    <authors>Alessandro Del Sole</authors>
    <owners>Alessandro Del Sole</owners>
    <licenseUrl>http://opensource.org/licenses/MIT</licenseUrl>
    <!-- Removing these lines as they are not needed
    <projectUrl>http://PROJECT_URL_HERE_OR_DELETE_THIS_LINE</projectUrl>
    <iconUrl>http://ICON_URL_HERE_OR_DELETE_THIS_LINE</iconUrl>-->
    <requireLicenseAcceptance>true</requireLicenseAcceptance>
    <description>Companion sample for the "Build and Deploy Libraries
    with Integrated Roslyn Code Analysis to NuGet" article
    on MSDN Magazine</description>
    <releaseNotes>First release.</releaseNotes>
    <copyright>Copyright 2015, Alessandro Del Sole</copyright>
    <tags>RSS, analyzers, Roslyn</tags>
    <frameworkAssemblies>
      <frameworkAssembly assemblyName="System" targetFramework="" />
    </frameworkAssemblies>
  </metadata>
  <files>
    <file src="*.dll" target="analyzers\dotnet\cs"
          exclude="**\Microsoft.CodeAnalysis.*;
          **\System.Collections.Immutable.*;**\System.Reflection.Metadata.*;
          **\System.Composition.*" />
    <file src="tools\*.ps1" target="tools\" />
    <file src="lib\FeedLibrary.dll" target="lib\portable-net451+netcore451+wpa81\"/>
  </files>
</package>

L'attributo src indica la posizione di origine per la raccolta e destinazione specifica la sottocartella di destinazione, in base al nome di profilo appropriato. In questo caso, Visual Studio eseguirà la ricerca di una raccolta denominata FeedLibrary.dll all'interno di una cartella denominata lib, è necessario creare nella directory corrente. Il secondo è la cartella che contiene l'analizzatore compilata, in genere il Debug o rilascio cartella, a seconda della configurazione di compilazione selezionata. Basato sull'esempio corrente, è necessario creare una cartella denominata lib all'interno della cartella della versione, quindi copiare il FeedLibrary.dll (generato quando si compila la libreria di esempio all'inizio) nella cartella lib. Una volta fatto questo, è semplicemente possibile ricompilare la soluzione e Visual Studio genera un pacchetto NuGet aggiornato che contiene la libreria sia l'analizzatore di Roslyn.

Vale la pena notare che, quando si ricompila il progetto, Visual Studio 2015 Aggiorna automaticamente i numeri di versione di build e di revisione del pacchetto NuGet, ignorando i numeri forniti nel tag di versione. È possibile analizzare facilmente il contenuto aggiornato del pacchetto NuGet aprendo la versione aggiornata, più elevata del pacchetto NuGet con uno strumento di archiviazione con estensione zip. Va ricordato che, Ogni volta che si modifica il valore dell'elemento id, come in Figura 9, Visual Studio 2015 genera un pacchetto NuGet con un nome diverso, in base al nuovo id. In questo caso, la modifica del valore di id con RSSFeedLibrary risultati in un pacchetto NuGet denominato RSSFeedLibrary.1.0.xxx.yyy.NuPkg, dove xxx rappresenta il numero di versione di build e yyy è il numero di revisione, entrambi vengono fornite automaticamente in fase di compilazione. A questo punto, raggiungere l'obiettivo del primo: creazione di pacchetti personalizzate API con integrato Roslyn analisi in un pacchetto NuGet.

In alternativa, è possibile creare (e pubblicare) due pacchetti separati, uno per l'analisi e uno per la libreria e un terzo vuoti pacchetto NuGet che mette insieme per risolvere il problema come dipendenze. Con questo approccio, è possibile decidere di mantenere le dimensioni di installazione più piccoli tramite le API solo senza l'analizzatore, anche se è necessario avere familiarità con le convenzioni di NuGet per creare manualmente un pacchetto da zero. Prima di pubblicare il pacchetto appena generato nel repository NuGet online, è opportuno testarlo localmente.

Test di un pacchetto NuGet in locale

Visual Studio 2015 consente il prelievo pacchetti NuGet dal repository locale. Ciò è molto utile, specialmente in situazioni in cui è necessario ai pacchetti della cache utilizzate di frequente o che potrebbero essere necessari quando si lavora offline. Si noti che questa è una buona soluzione quando il numero di pacchetti nella cartella locale è piccolo. Se si dispone di centinaia di pacchetti, sarebbe molto più complesso da gestire. Per testare il pacchetto NuGet generato in precedenza, creare una nuova cartella sul disco chiamato LocalPackages, quindi copiare la versione più recente del file RSSFeedLibrary.1.0.xxx.yyy.nupkg in questa cartella. Il passaggio successivo è consentire di Visual Studio 2015 selezionare i pacchetti contenuti nella cartella locale specificata, come illustrato nella Figura 10; selezionare strumenti | Opzioni | Gestione pacchetti NuGet | Origini del pacchetto e, nella finestra Origini pacchetto disponibili, fare clic sul pulsante Aggiungi (il simbolo di addizione in verde). A questo punto, nelle caselle di testo Nome e di origine digitare pacchetti locali e C:\LocalPackages, rispettivamente. Infine, fare clic su Aggiorna per aggiornare l'elenco delle origini del pacchetto.

Aggiunta di un Repository locale come origine pacchetto NuGet
Figura 10 aggiunta di un Repository locale come origine pacchetto NuGet

Dopo aver creato il repository NuGet locale, creare una nuova applicazione console per testare la libreria più di un pacchetto di analisi Roslyn 2015 di Visual Studio. Salvare il progetto, quindi selezionare progetto | Gestisci pacchetti NuGet. Quando viene visualizzata la finestra di gestione pacchetti NuGet, selezionare l'origine di pacchetti locali nella casella combinata di origine del pacchetto. A questo punto, la gestione dei pacchetti verrà visualizzato un elenco dei pacchetti disponibili nel repository specificato, in questo caso il pacchetto di esempio.

Fai clic su Install. Come pacchetti NuGet in linea, Visual Studio verranno visualizzate informazioni di riepilogo per il pacchetto selezionato e verrà chiesto di accettare il contratto di licenza. Al termine dell'installazione, sarà in grado di visualizzare la libreria sia l'analizzatore di Roslyn in Esplora soluzioni, come illustrato nella Figura 11.

La libreria e l'analizzatore di Roslyn è stati installati tramite il pacchetto NuGet
Figura 11 sia la libreria e l'analizzatore di Roslyn è stati installati tramite il pacchetto NuGet

Se è sufficiente scrivere del codice che utilizza il metodo FeedItem.ParseFeedAsync per passare un URL non valido come argomento, il motore di analisi live segnalerà un messaggio di avviso, come previsto (vedere Figura 8 per riferimento).

Quando si installa un analizzatore, indipendentemente dal fatto se sia stato ottenuto dall'utente o da altri sviluppatori, è possibile esaminare i dettagli di ogni regola in Esplora soluzioni, espandere i riferimenti, analisi e il nome dell'analizzatore di. In questo caso, è possibile espandere il nome del FeedLibraryAnalyzer e visualizzare la regola di analisi di URL di RSS, come illustrato nella Figura 11. Quando si fa clic su una regola, la finestra proprietà verranno visualizzate informazioni dettagliate quali l'impostazione predefinita e gravità efficace, se è abilitato per impostazione predefinita e la descrizione della regola completa. Inoltre, è possibile utilizzare l'Editor di Ruleset per visualizzare tutte le regole applicabili a un progetto e per visualizzare o modificare la gravità della regola, nonché la disabilitazione o abilitazione analizzatori e regole. Per aprire l'Editor set di regole, in Esplora soluzioni fare doppio clic su proprietà, quindi selezionare la scheda analisi codice nella finestra delle proprietà del progetto, infine fare clic su Apri, lasciando invariato il set di regole predefinito.

Come si può notare dalle Figura 11, è possibile disabilitare/abilitare una regola da Seleziona/deseleziona la casella di controllo vicino il codice di regola, è possibile modificare il livello di gravità predefinito facendo clic su nero freccia giù a destra del livello di gravità corrente (questa operazione può inoltre essere eseguita facendo la regola in Esplora soluzioni e selezionando quindi impostare regola impostare gravità dal menu di scelta rapida). Quando si è soddisfatti dei test locali, è possibile spostare alla pubblicazione online il pacchetto NuGet.

Test di un pacchetto in linea

In NuGet, gli sviluppatori si aspettano trovare pacchetti professionali di alta qualità. Per questo motivo, prima di pubblicare un pacchetto per la raccolta NuGet in linea, è necessario verificare il lavoro con l'aiuto di un servizio online che consente di creare privata repository NuGet e feed e laurearsi al repository NuGet ufficiale una volta il pacchetto è stabile. Una buona scelta viene offerta da MyGet (myget.org), un servizio online che consente di creare personali e aziendali NuGet feed, più feed VSIX, npm e Bower. MyGet offre un piano gratuito con le funzionalità più comuni necessarie per pubblicare e utilizzare pacchetti NuGet; il piano gratuito non consentono di creare feed privato (è necessario un piano a pagamento per cui), ma è un'ottima scelta per verificare se i pacchetti di funzionano come previsto da un repository in linea. Quando si registra, è disponibile un'opzione per creare un feed di NuGet. Ad esempio, il feed pubblico in MyGet è disponibile all'indirizzo myget.org/F/aledelsole/api/v2. Spiega come lavorare con MyGet esula dall'ambito di questo articolo, ma la documentazione completa viene descritto come configurare i feed di NuGet. Dopo aver creato un feed e pubblicato il pacchetto, è sufficiente abilitare Visual Studio 2015 scegliere i feed di MyGet pacchetti NuGet. A tale scopo, è possibile seguire i passaggi descritti nella sezione precedente e richiedere Figura 10 come riferimento, fornendo il MyGet feed dell'URL. Per scaricare e testare un pacchetto in Visual Studio, si saranno comunque seguire i passaggi descritti nella sezione precedente, ovviamente selezionando il MyGet feed come origine nella finestra di gestione pacchetti NuGet.

Pubblicazione di un pacchetto per la raccolta NuGet in linea

Per pubblicare i pacchetti al repository NuGet online, è necessario aprire nuget.org e accedere con un account. Se ancora non si dispone di un account, fare clic sul collegamento ipertestuale Register/Accedi nell'angolo superiore destro della pagina. È possibile accedere con un Account Microsoft (scelta consigliata) o con le credenziali di nome utente/password. Dopo aver registrato, fare clic su Carica pacchetto. La prima cosa che verrà chiesto consiste nello specificare il pacchetto NuGet che si desidera caricare, quindi fare clic su Sfoglia, selezionare la versione più recente del RSSFeedLibrary.1.0.xxx.yyy.nupkg dal disco e quindi fare clic su Carica.

Verrà ora richiesto con le informazioni sui metadati per il pacchetto. Di seguito è disponibile un'opzione per esaminare i dettagli del pacchetto prima di pubblicarlo alla raccolta, come illustrato nella Figura 12. Quando si è pronti, fare clic su Invia. A questo punto, il pacchetto che contiene l'API sia l'analizzatore Roslyn integrata verrà pubblicato nella raccolta NuGet. Si noti che occorrono 15-20 minuti prima di poter visualizzare il pacchetto disponibile nella finestra Gestione pacchetti NuGet in Visual Studio 2015.

Esaminare i dettagli del pacchetto prima della pubblicazione
Figura 12, esaminare i dettagli del pacchetto prima della pubblicazione

Dopo che il pacchetto è elencato nella raccolta, sarà possibile installarlo nel progetto dal repository NuGet online, come illustrato nella Figura 13. Una volta installato, si utilizzerà la libreria come illustrato nella sezione precedente, l'analisi del codice specifico di dominio, live integrato con tecnologia .NET Compiler Platform.

Il pacchetto NuGet è disponibile al pubblico dall'archivio in linea
Figura 13 il pacchetto NuGet è disponibile al pubblico dall'archivio in linea

Aggiornamenti del pacchetto

Come per tutti i pacchetti NuGet, è possibile migliorare le librerie e inserire una versione aggiornata del pacchetto NuGet. Per creare un pacchetto aggiornato, è sufficiente ricompilare la soluzione e Visual Studio 2015 aggiornerà automaticamente il numero di versione del pacchetto. Quindi ricompilare il progetto e ripetere i passaggi descritti in precedenza per pubblicare il pacchetto NuGet in linea. NuGet consente di gestire un elenco delle versioni disponibili per ogni pacchetto e consentirà agli sviluppatori di scegliere la versione di che cui hanno bisogno.

Avvolgendo

Uno dei maggiori vantaggi offerti dalla piattaforma del compilatore .NET è che è possibile creare codice specifico di dominio le regole di analisi per l'API. In questo articolo, ho innanzitutto illustrato come creare una libreria di esempio, quindi come creare un analizzatore Roslyn che rileva problemi nel codice durante la digitazione, specifiche per i membri della raccolta. Successivamente, ho illustrato come incorporare la libreria e l'analisi in un pacchetto NuGet, che è il nucleo dell'articolo. In questo modo, gli sviluppatori che hanno scaricato il pacchetto NuGet otterrà le API con analisi live Roslyn integrata. È quindi stata spostata illustrare come eseguire il test in locale, il pacchetto NuGet prima della pubblicazione in linea. Questo passaggio è molto importante perché si dispone di un'opportunità per verificare che la coppia/analyzer libreria funziona correttamente prima di renderlo disponibile al pubblico. Ma il bello quando altri sviluppatori possono utilizzare il risultato del lavoro, quindi nell'ultima sezione dell'articolo ho illustrato come pubblicare il pacchetto nel repository NuGet online e come può essere successiva installato nei progetti di Visual Studio. Distribuzione di analizzatori Roslyn con le librerie senz'altro aumenta il valore del lavoro, fornendo un'esperienza migliore codifica ad altri sviluppatori.


Alessandro Del Soleè stato un MVP Microsoft dal 2008. Assegnati MVP di cinque volte l'anno, egli ha scritto molti libri, eBook, video didattici e articoli sullo sviluppo .NET con Visual Studio. È possibile seguirlo su Twitter @progalex.

Grazie ai seguenti esperti tecnici per la revisione di questo articolo: Srivatsn Narayanan e Vasani Manish
Srivatsn Narayanan ha lavorato in lingue (IronPython, c#, VB.NET) di Microsoft negli ultimi otto anni. Egli ha lavorato sui compilatori e gli sforzi di servizi di linguaggio per queste lingue e più di recente è stato leader di impegno per sviluppare il framework di analyzer\fixer Roslyn.

Manish Vasani è software engineer con otto anni di esperienza lavorando con diversi team nel gruppo di Visual Studio in Microsoft. Egli è attualmente nel team di linguaggi gestiti di Analysis Services, dove è responsabile dell'analizzatore di Roslyn API, infrastruttura di esecuzione analyzer e l'integrazione con Visual Studio.