<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 代碼分析 - 借助與 NuGet 集成的 Roslyn 代碼分析來生成和部署庫 作者:?[Alessandro Del Sole](https://msdn.microsoft.com/zh-cn/magazine/mt149362?author=Alessandro+Del+Sole)?| 2015 年 10 月 | 獲取代碼:?[C#](https://msdn.microsoft.com/zh-cn/magazine/mt573715.aspx#)[VB](https://msdn.microsoft.com/zh-cn/magazine/mt573715.aspx#) Microsoft .NET 編譯器平臺(也稱為“Roslyn”代碼庫)提供了大量代碼分析 API 的開放式源 C# 和 Visual Basic 編譯器,使你可以生成要集成到 Visual Studio 2015 代碼編輯器的實時分析規則。有了 .NET 編譯器平臺,你可以編寫自定義、特定于域的代碼分析器和重構功能,使 Visual Studio 可以檢測你鍵入的代碼問題并報告警告和錯誤消息。.NET 編譯器平臺的一大優勢是可實現代碼分析器與 API 的捆綁。譬如說,如果要生成庫或可重用的用戶控件,可以將分析器與庫一起提供,并為開發人員提供良好的編碼體驗。 在本文中,我將介紹如何將庫和分析器捆綁到 NuGet 包以用于在線部署,并向你演示如何為 API 提供集成 Roslyn 代碼分析。你至少需要對 .NET 編譯器平臺的概念以及代碼分析器的編寫稍微了解一些。有關這兩個主題的文章之前在 MSDN 雜志上發表過,文章的作者是 Alex Turner,文章名為 “C# 和 Visual Basic: 使用 Roslyn 編寫 API 的實時代碼分析器” ([msdn.microsoft.com/magazine/dn879356](https://msdn.microsoft.com/magazine/dn879356)) 和“將代碼修補程序添加到 Roslyn 分析器” ([msdn.microsoft.com/magazine/dn904670](https://msdn.microsoft.com/magazine/dn904670)),我們強烈建議你先閱讀這兩篇文章,然后再繼續。 ## 準備一個示例庫來模擬自定義 API 你首先需要一個類庫用來模擬自定義 API。本文借助于示例庫向大家展示一個簡單的公用方法,即從 RSS 源檢索公共信息并返回源項的集合。在 Visual Studio 2015 中,使用 C# 或 Visual Basic 創建一個新的可移植類庫,名為 FeedLibrary,并確保最低目標是適用于 Windows 8.1、Windows Phone 8.1 和 Microsoft .NET Framework 4.5.1。有了這個目標,該庫也可以利用 Async/Await 模式,沒有任何其他要求。 將 Class1.vb 或 Class1.cs 生成的文件重命名為 FeedItem.vb/.cs。該類的 C# 代碼如圖 1?所示,Visual Basic 代碼如圖 2?所示。 圖 1 在 C# 中實現從 RSS 源檢索公共項的類 ~~~ 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; ????? } ??? } ? } } ~~~ 圖 2 在 Visual Basic 中實現從 RSS 源檢索公共項的類 ~~~ 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 ~~~ 這段代碼很簡單: 它從指定 RSS 源的 URL 下載整合的內容、為每個源項創建 Feed-Item 類的實例并最終返回一組新項。若要使用該庫,只需對于 C# 調用靜態 ParseFeedAsyncAsync 方法即可,如下所示: ~~~ // Replace the argument with a valid URL var items = await FeedItem.ParseFeedAsyncAsync("http://sampleurl.com/rss"); ~~~ 而對于 Visual Basic,調用方法如下所示: ~~~ 'Replace the argument with a valid URL Dim items = Await FeedItem.ParseFeedAsyncAsync("http://sampleurl.com/rss") ~~~ 該調用返回 IEnumerable,你隨后可以根據需要使用它。選擇發布配置并生成項目;此時,Visual Studio 2015 將生成一個名為 FeedLibrary.dll 的庫,以供后續使用。 ## 編寫 Roslyn 分析器 下一步是創建 Roslyn 分析器,為自定義 API 提供特定于域的實時分析規則。該分析器將使用 Uri.IsWellFormedUriString 方法檢測作為 ParseFeedAsyncAsync 方法自變量提供的 URL 是否正確;如果不正確,分析器在你鍵入內容時將報告警告消息。當然,檢測 URL 是否無效的方法還有很多,但是這種方法較簡單。此外,出于同樣原因,分析器將提供實時分析報告警告,但是它不提供任何代碼修復,這部分內容留給你自己練習。然后執行以下步驟: 1. 在 Solution Explorer(解決方案資源管理器)中,右鍵單擊解決方案名稱,然后選擇“Add | New Project”(添加 | 新建項目)。 2. 在項目模板列表的“Extensibility”(可擴展性)節點中,選擇“Analyzer with Code Fix”(帶有代碼修補程序的分析器)(NuGet + VSIX)。注意,Extensibility(可擴展性)節點在默認情況下不顯示。你首先需要下載 .NET 編譯器平臺 SDK 才能提取 Analyzer with Code Fix(帶有代碼修補程序的分析器)模板項目。在“New Project”(新建項目)對話框中搜索分析器,然后你會看到要下載此 SDK 的模板項目。 3. 調用新分析器 FeedLibraryAnalyzer 并單擊“OK”(確定)。 4. 當新項目就緒時,刪除 CodeFix-Provider.cs(或 .vb)文件。 在 DiagnosticAnalyzer.cs(或 .vb)文件中,首先要做的是根據編碼經驗提供用來標識分析器的字符串。為了簡化分析器的實現,在當前示例中,我使用常規字符串替代 LocalizableString 對象和資源文件,而且假設分析器不需要本地化。對于 C#,重寫診斷 ID、標題、消息、描述和類別,如下所示: ~~~ 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"; ~~~ 對于 Visual Basic,如下所示: ~~~ 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" ~~~ 不要更改診斷的嚴重性,它在默認情況下為“警告”,而且適用于當前示例。現在,讓我們把重點放在分析邏輯上。分析器必須檢查代碼是否正在調用名為 ParseFeedAsync 的方法。如果是,分析器隨后將檢查所提供的 URL 是否正確。借助于 Syntax Visualizer(語法可視化工具),可以看到 Invocation-Expression 如何調用 ParseFeedAsync 方法,這里 Invocation-Expression 的類型應該為 InvocationExpressionSyntax,如圖 3?所示。 ![](https://box.kancloud.cn/2016-01-08_568f4ae787c05.png) 圖 3 Syntax Visualizer(語法可視化工具)可以找到正確的語法節點表示法 所以,分析器僅關注類型為 Invocation-ExpressionSyntax 的對象;發現此類對象時,會將關聯的表達式轉換為類型為 MemberAccessExpressionSyntax 的對象,它包含有關方法調用的信息。如果轉換成功,分析器將檢查方法是否為 ParseFeedAsync,然后檢索第一個自變量,并對其值執行實時分析。這是通過名為 AnalyzeMethod 的新方法實現的,并在 SyntaxNode 級別工作,圖 4?所示適用于 C#,圖 5?所示適用于 Visual Basic。 圖 4 在 C# 中檢測 ParseFeedAsync 自變量的問題 ~~~ 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); ? } } ~~~ 圖 5 在 Visual Basic 中檢測 ParseFeedAsync 自變量的問題 ~~~ 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 ~~~ 此時,你需要編輯 Initialize 方法使其調用新添加的 AnalyzeMethodInvocation 方法,圖 6所示適用于 C#,圖 7所示適用于 Visual Basic。 圖 6 在 C# 中編輯 Initialize 方法 ~~~ 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); ? }); } ~~~ 圖 7 在 Visual Basic 中編輯 Initialize 方法 ~~~ 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 ~~~ 觀察代碼最開始的檢查方式以判斷項目中是否存在對庫的調用,這需要通過調用 Compilation.GetTypeMetadataName 方法來實現,而且為了確保引用已經添加,其自變量必須是當前環境中已經存在的類型的名稱。如果該調用返回 null,則說明類型不存在,尚未向庫添加任何引用。所以,無需注冊代碼分析操作即可提高分析器的性能。現在,如果按下 F5 在 Visual Studio 2015 的實驗實例中測試分析程序并創建具有 FeedLibrary 庫引用的新項目,那么你每次提供無效 URL 時,它都會正確報告警告消息,如圖 8?所示。 ![](https://box.kancloud.cn/2016-01-08_568f4ae7aff2e.png) 圖 8 如果 URL 不正確,分析器將報告警告消息 到目前為止,你已經生成了 API,以及相關的特定于域的代碼分析規則。現在,讓我們看看如何將兩者綁定到一個 NuGet 包。 ## 將 API 和分析器綁定到一個 NuGet 包 Analyzer with Code Fix(帶有代碼修補程序的分析器)項目模板的 MSBuild 規則是自動生成包含編譯分析器的 NuGet 包,你可將其發布到 NuGet 存儲庫與其他開發人員共享。事實上,每次你按下 F5 調試分析器或者每次你生成分析器項目時,Visual Studio 2015 都會重新生成分析器 .dll 文件(在當前示例中是 Feed-LibraryAnalyzer.dll),以及一個包含該分析器的可再發行的 NuGet 包。 在生成過程中同時生成的還有一個 VSIX 包,也可發布到 Visual Studio 庫,它也能夠在 Visual Studio 2015 的實驗實例內調試分析器,但是此內容超出本文范圍,在這里不過多講述。 若想與集成的 Roslyn 分析共享庫,則需要向生成項目時 Visual Studio 2015 生成的 NuGet 包添加庫。執行此操作之前,你需要了解分析器的 NuGet 包的生成方式。事實上,NuGet 包是一個 .zip 存檔,擴展名為 .nupkg。因此,你可以使用 .zip 存檔工具輕松查看 NuGet 包的內容和結構,可用工具有 Windows 資源管理器壓縮文件夾工具、WinZip 或 WinRar。下面總結了 NuGet 包中部署分析器時需要注意的重要事項: * .nuspec 文件: 該文件包含包元數據,并且包含發布所需的信息,比如包名稱、版本、描述、作者以及許可 URL 等。.nuspec 文件綁定到 NuGet 包,它基于 Solution Explorer(解決方案資源管理器)中分析器項目內的 Diagnostic.nuspec 文件。你很快就可以在 Visual Studio 2015 中編輯 Diagnostic.nuspec。 * 工具文件夾: 該文件夾包含的 Windows PowerShell 腳本可由 Visual Studio 用來安裝 (Install.ps1) 和卸載 (Uninstall.ps1) 指定項目的分析器。 * 分析器文件夾: 該文件夾包含可整理到特殊子文件夾中的分析器.dll 文件。無關的分析器庫(面向所有語言)保存在子文件夾 dotnet 中。面向 C# 的分析器保存在 dotnet\cs 子文件中,而面向 Visual Basic 的分析器保存在 dotnet\vb 文件夾中。有必要提一下,dotnet 代表 .NET Core 的配置文件,支持通用 Windows 應用和 ASP.NET 5 項目之類的項目類型。 可以綁定到 NuGet 包的其他項目還有很多,但是這里我關注的是為 Roslyn 分析器生成的典型包,所以只討論所需的項。 任何可以從 Visual Studio 項目引用的庫都必須整理到 lib 文件夾中。由于庫可以面向不同平臺,比如不同版本的 .NET Framework、Windows 運行時、不同版本的 Windows Phone 甚至是可移植子集(包括 Xamarin 庫),所以 lib 文件夾必須包含每個目標平臺的子文件夾,而且每個子文件夾還必須包含要部署的庫的副本。每個子文件夾的名稱必須與表示特定平臺的配置文件的名稱匹配。例如,你有一個面向 .NET Framework 4.5.1 和 Windows 8.1 的庫,那么你的結構如下:net451 表示 .NET Framework 4.5.1 的配置文件名稱,而 netcore451 表示 Windows 8.1 中 Windows 運行時的配置文件名稱: ~~~ lib\net451\mylib.dll lib\netcore451\mylib.dll ~~~ 值得一提的是,面向通用 Windows 平臺 (UWP) 的 uap10.0 配置文件用來生成 Windows 10 應用。受支持配置文件的完整列表在 NuGet 文檔中提供。之前創建的示例庫是面向 .NET Framework 4.5.1、Windows 8.1 和 Windows Phone 8.1 的可移植庫。這類目標的配置文件名稱是 portable-net451+netcore451+wpa81,將在 NuGet 包中包含庫的子文件夾必須使用此名稱來命名。你無需手動創建子文件夾并復制庫;你只需在 Visual Studio 內編輯 NuGet 包元數據(Diagnostic.nuspec 文件)即可。圖 9?顯示了更新后的元數據,其中包含有關發布的正確信息(ID、標題、作者、描述、許可等),還在文件節點中顯示了一個新文件元素,用來指定源文件和目標子文件夾。 圖 9 編輯 NuGet 包元數據 ~~~ <?xml version="1.0"?> <package xmlns="http://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> ~~~ src 屬性指示庫的源位置,而 target 指定目標文件夾,它們都基于正確的配置文件名稱。在這種情況下,Visual Studio 將在 lib 文件夾內搜索庫 FeedLibrary.dll,你需要在當前目錄中創建該文件夾。當前文件夾中包含編譯分析器,通常是 Release 或 Debug 文件夾,根據所選生成配置的不同而不同。根據當前示例,你需要在 Release 文件夾內創建文件夾 lib,然后將 FeedLibrary.dll(通常在開始編譯示例庫時生成)復制到 lib 文件夾中。一旦完成此操作,你只需重新生成解決方案即可,Visual Studio 將生成更新的 NuGet 包,同時將庫和 Roslyn 分析器包含在內。 值得注意的是,當你重新生成項目時,Visual Studio 2015 將自動更新 NuGet 包的內部版本號和修訂版本號,不考慮版本標記提供的號。使用 .zip 存檔工具打開更新的、最高版本的 NuGet 包,即可輕松查看 NuGet 包的更新內容。請記住: 如圖 9?所示,每次你更改 id 元素的值時,Visual Studio 2015 都會根據新 id 生成一個不同名的 NuGet 包。在這種情況下,更改 RSSFeedLibrary 的 id 值會生成名為 RSSFeedLibrary.1.0.xxx.yyy.NuPkg 的 NuGet 包,其中 xxx 指內部版本號,yyy 指修訂版本號,兩個號都是生成時自動提供的。此時,你已經實現了第一個目標,即借助集成式 Roslyn 分析將自定義 API 封裝到 NuGet 包。 或者,你也可以為分析器和庫各創建(和發布)一個單獨的包,另外再創建一個空 NuGet 包,將它們視為依賴項而存放在一起。通過這種方式,你可以選擇僅使用 API 而不使用分析器以便減小安裝大小,但是你需要熟悉 NuGet 約定才能從頭開始手動創建包。向在線 NuGet 存儲庫發布新生成的包之前,最好本地測試一下。 ## 本地測試 NuGet 包 Visual Studio 2015 支持從本地存儲庫選取 NuGet 包。尤其當你緩存經常使用的包或者可能在脫機工作時使用的包時,這非常有用。注意,如果本地文件夾中的包很少,這種方法非常適用;但是如果有數百個包,則處理起來會非常復雜。為了測試之前生成的 NuGet 包,在磁盤上創建一個名為 LocalPackages 的新文件夾,然后將最新版本的 RSSFeed-Library.1.0.xxx.yyy.nupkg 文件復制到該文件夾中。下一步是讓 Visual Studio 2015 從指定的本地文件夾選取包,如圖 10?所示;在“Available package sources”(可用包源)框中,選擇“Tools | Options | NuGet Package Manager | Package Sources”(工具 | 選項 | NuGet 包管理器 | 包源),然后單擊“Add”(添加)按鈕(綠色的加號)。在“Name”(名稱)和“Source”(源)文本框中,分別鍵入 Local packages 和 C:\LocalPackages。最后,單擊“Update”(更新)刷新包源的列表。 ![](https://box.kancloud.cn/2016-01-08_568f4ae7cb6ef.png) 圖 10 將 Local Repository 添加為 NuGet Package Source 現在你有了自己的本地 NuGet 存儲庫,在 Visual Studio 2015 中創建新的控制臺應用程序來測試庫以及 Roslyn 分析包。保存項目,然后選擇“Project | Manage NuGet Packages”(項目 | 管理 NuGet 包)。當“NuGet Package Manager”(NuGet 包管理)窗口出現時,在“Package source”(包源)組合框中選中“Local packages source”。此時,包管理器將顯示指定存儲庫內可用包的列表,在本示例中只有示例包。 單擊“安裝”。在線推出 NuGet 包后,Visual Studio 將顯示所選包的摘要信息,并且要求你接受許可協議。安裝完成時,你可以在 Solution Explorer(解決方案資源管理器)中看到該庫和 Roslyn 分析器,如圖 11?所示。 ![](https://box.kancloud.cn/2016-01-08_568f4ae7e6cc3.png) 圖 11 庫和 Roslyn 分析器都通過 NuGet 包安裝 如果你只是編寫一些代碼指定 FeedItem.ParseFeed-Async 方法將無效 URL 傳遞為自變量,則實時分析引擎將按預期報告警告消息(請參閱圖 8?獲取更多信息)。 安裝分析器時,無論它是由你還是其他開發人員生成的,只要在 Solution Explorer (解決方案資源管理器)中展開“References”(引用)、“Analyzers”(分析器)以及分析器的名稱,即可看到每條規則的詳細信息。在本示例中,可以展開 FeedLibraryAnalyzer 的名稱并查看 RSS URL 分析規則,如圖 11所示。當你單擊某個規則時,如果它在默認情況下啟用,則 Properties (屬性)窗口將顯示默認值和有效嚴重性之類的詳細信息,以及完整的規則描述。此外,可以使用 Ruleset Editor(規則集編輯器)查看適用于項目的所有規則、查看或更改規則的嚴重性,以及禁用或啟用分析器和規則。在 Solution Explorer(解決方案資源管理器)中打開“Ruleset Editor”(規則集編輯器),雙擊“Properties”(屬性),然后在項目的“Properties”(屬性)窗口中選擇“Code Analysis”(代碼分析)選項卡,不更改默認規則集。 如圖 11?所示,可以通過取消選中/選中規則代碼旁邊的復選框來禁用/啟用規則;可以通過單擊當前嚴重性級別右側的黑色向下箭頭來更改默認的嚴重性,也可通過右鍵單擊 Solution Explorer(解決方案資源管理器)中的規則并從上下文菜單中選擇“Set Rule Set Severity”(設置規則集嚴重性)來實現。如果你對本地測試滿意,可以在線發布 NuGet 包。 ## 在線測試包 在 NuGet 上,開發人員希望獲得更高質量、更專業的包。為此,向在線 NuGet 庫發布包之前,應該通過在線服務來測試工作內容,它支持你創建私有 NuGet 存儲庫和源,并且在包穩定后升級到正式 NuGet 存儲庫。MyGet ([myget.org](http://myget.org/)) 提供了一項非常好的選擇,其在線服務支持創建個人和企業 NuGet 源以及 VSIX、npm 和 Bower 源。MyGet 提供了免費使用計劃,NuGet 包發布和使用所需的大部分功能都是免費的;這個免費計劃不支持創建私有源(你需要為此付費),但是你可以利用它從在線存儲庫測試你的包是否如預期運行。當你注冊時,你可以選擇創建 NuGet 源。例如,我在 MyGet 上的公有源存放在 myget.org/F/-aledelsole/api/v2。MyGet 的用法不在本文范圍內,但是本文詳細說明了如何配置 NuGet 源。一旦創建了源并發布了包,只需讓 Visual Studio 2015 從 MyGet 源選取 NuGet 包即可。為此,可以遵循上一節中描述的步驟,并參考圖 10?來提供 MyGet 源的 URL。要下載并在 Visual Studio 中測試包,仍然需要遵循上一節中描述的步驟,在“NuGet Package Manager”(NuGet 包管理器)窗口中選擇 MyGet 源作為源。 ## 將包發布到在線 NuGet 庫 要將包發布到在線 NuGet 庫,你需要打開?[nuget.org](http://nuget.org/),然而使用帳戶登錄。如果你還沒有帳戶,則單擊頁面右上角的“Register/Sign In”(注冊/登錄)超鏈接。可以使用 Microsoft 帳戶(推薦)或用戶名/密碼憑據登錄。注冊后,單擊“Upload Package”(上載包)。首先會要求你指定要上載的 NuGet 包,所以單擊“Browse”(瀏覽)、從磁盤選擇最新版本的 RSSFeed-Library.1.0.xxx.yyy.nupkg,然后單擊“Upload”(上載)。 接下來會提示你輸入包的元數據信息。此時,你可以先檢查包詳細信息,之后再向庫發布,如圖 12?所示。檢查好后,單擊“Submit”(提交)。這樣,包含 API 和集成式 Roslyn 分析器的包就會發布到 NuGet 庫。注意,這通常會占用 15 - 20 分鐘時間,之后你才能在 Visual Studio 2015 的 NuGet Package Manager(NuGet 包管理器)窗口中看到包。 ![](https://box.kancloud.cn/2016-01-08_568f4ae814466.png) 圖 12 發布前檢查包詳細信息 當包在庫中列出后,你可以從在線 NuGet 存儲庫將它安裝到項目中,如圖 13?所示。安裝后,你可以如上一節中所述對庫執行 .NET 編譯器平臺的集成式、實時、特定于域的代碼分析。 ![](https://box.kancloud.cn/2016-01-08_568f4ae82eb0c.png) 圖 13 NuGet 包已在在線存儲庫中公開推出 ## 包更新 對于任何 NuGet 包,你都可以改善庫并向 NuGet 發布更新的包版本。要創建更新的包,你只需重新生成解決方案即可,Visual Studio 2015 將自動更新包版本號。然后,重新生成項目并重復上一節中描述的步驟來發布在線 NuGet 包。NuGet 將管理每個包的可用版本的列表,它允許開發人員選擇所需版本。 ## 總結 .NET 編譯器平臺的一大優勢是你可以通過它為自己的 API 創建特定于域的代碼分析規則。在本章中,我首先介紹了如何創建示例庫,然后介紹了如何創建檢測鍵入時代碼問題的 Roslyn 分析器,具體針對庫的成員。接下來,我介紹了如何將庫和分析器綁定到一個 NuGet 包,這是本文的核心部分。學會了這部分內容,開發人員即可在下載 NuGet 包后在 API 上實現集成式 Roslyn 實時分析。然后,我介紹了如何在在線發布之前先本地測試 NuGet 包。這一步非常重要,因為你可以在將信息公布之前驗證庫和分析器是否正確運行。但是其他開發人員何時可以使用你的工作成果?我在本文的最后一部分講述了如何將包發布到在線 NuGet 存儲庫,以及它后續如何從 Visual Studio 安裝到項目中。可以肯定的說,部署 Roslyn 分析器和庫能夠提高你的工作價值,而且可以為其他開發人員提供更豐富的編碼經驗。 * * * Alessandro Del Sole?*自 2008 年起被評為 Microsoft MVP。他已經 5 次獲得年度 MVP 這一殊榮,發表過很多關于 Visual Studio .NET 開發的書籍、電子書、指導視頻和文章。你可以關注他的 Twitter[@progalex](http://twitter.com/@progalex)。*
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看