6

次のコマンドを使用したカスタム msbuild タスクがあります。

var workspace = Workspace.LoadStandAloneProject(csprojPath);

実行すると、次のエラーがスローされます。

  System.InvalidCastException がユーザー コードによって処理されませんでした
  Message='Roslyn.Utilities.SerializableDataStorage' 型に透過プロキシをキャストできません。
  ソース=Roslyn.Services
  スタックトレース:
       Roslyn.Utilities.RemoteServices.CreateInstance[T]() で
       Roslyn.Services.Host.TemporaryStorageServiceFactory.CreateService (IWorkspaceServiceProvider ワークスペース サービス) で
       Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.c__DisplayClass7.b__4() で
       Roslyn.Utilities.NonReentrantLazy`1.get_Value() で
       Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.GetService[TWorkspaceService]() で
       Roslyn.Services.SolutionServices..ctor (IWorkspaceServiceProvider ワークスペース サービス、ILanguageServiceProviderFactory 言語サービス ファクトリー) で
       Roslyn.Services.Solution..ctor (SolutionId id、文字列 filePath、VersionStamp バージョン、VersionStamp latestProjectVersion、ILanguageServiceProviderFactory languageServiceProviderFactory、IWorkspaceServiceProvider ワークスペースサービス) で
       Roslyn.Services.Host.SolutionFactoryServiceFactory.SolutionFactoryService.CreateSolution (SolutionId id) で
       Roslyn.Services.Host.TrackingWorkspace.CreateNewSolution (ISolutionFactoryService solutionFactory、SolutionId id) で
       Roslyn.Services.Host.TrackingWorkspace..ctor (IWorkspaceServiceProvider ワークスペースServiceProvider、ブール値の enableBackgroundCompilation、ブール値の enableInProgressSolutions) で
       Roslyn.Services.Host.HostWorkspace..ctor (IWorkspaceServiceProvider ワークスペースServiceProvider、ブール型の e​​nableBackgroundCompilation、ブール型の e​​nableInProgressSolutions、ブール型の e​​nableFileTracking) で
       Roslyn.Services.Host.LoadedWorkspace..ctor (ILanguageServiceProviderFactory languageServiceProviderFactory、IWorkspaceServiceProvider ワークスペースServiceProvider、IProjectFileService projectFileFactsService、IDictionary`2 globalProperties、ブール値の enableBackgroundCompilation、ブール値の enableFileTracking) で
       Roslyn.Services.Host.LoadedWorkspace..ctor (ExportProvider exportProvider、ブール値の solutionLoadOnly、ブール値の enableFileTracking) で
       Roslyn.Services.Host.LoadedWorkspace..ctor (ブール値の enableFileTracking) で
       Roslyn.Services.Host.LoadedWorkspace.LoadStandAloneProject (文字列の projectFileName、文字列の構成、文字列のプラットフォーム、文字列の言語、ブール値の enableFileTracking) で
       Roslyn.Services.Workspace.LoadStandAloneProject (文字列の projectFileName、文字列の構成、文字列のプラットフォーム、文字列の言語、ブール値の enableFileTracking) で
       ...

コンソール アプリケーションで同じプロジェクトを使用して同じコードを実行すると、正常に動作します。

何か案は?グーグルは役に立ちませんでした!

4

2 に答える 2

4

Roslyn を使用したサンプル MsBuild タスクを次に示します。

Workspace.LoadProjectFromCommandLineArguments メソッドで必要なコマンド ラインを再構築するには、msbuild ファイルからタスクに情報を渡す必要があります。

  • 参照されるアセンブリ: @(ReferencePath) アイテム グループ。
  • コンパイルする cs ファイル: @(Compile) 項目グループ。
  • ベース ディレクトリ: $(MSBuildProjectDirectory) 組み込みプロパティ。

Roslyn がソース ファイルを解析するために必要なのはこれだけです。(この投稿の最後にある注を参照してください。)

そのため、C# クラス ライブラリ プロジェクトを作成します。必要なプロジェクト参照は次のとおりです。

Microsoft.Build.Framework
Microsoft.Build.Utilities.v4.0
Roslyn.Compilers
Roslyn.Services

カスタム MsBuild タスクのコード:

using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using Roslyn.Services;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RoslynMsBuildTask
{
    public class RoslynTask : Task
    {
        [Required]
        public ITaskItem[] ReferencePath { get; set; }

        [Required]
        public ITaskItem[] Compile { get; set; }

        [Required]
        public ITaskItem BaseDirectory { get; set; }

        public override bool Execute()
        {
            Log.LogMessage(MessageImportance.High, "RoslynTask.Execute called...\n");

            // Format the command line with the minimal info needed for Roslyn to create a workspace.
            var commandLineForProject = string.Format("/reference:{0} {1}",
                ReferencePath.Select(i => i.ItemSpec).ToSingleString(",", "\"", "\""),
                Compile.Select(i => i.ItemSpec).ToSingleString(" ", "\"", "\""));

            // Create the Roslyn workspace.
            var workspace = Workspace.LoadProjectFromCommandLineArguments("MyProject", "C#", commandLineForProject, BaseDirectory.ItemSpec);

            // Make sure that Roslyn actually parsed the project: dump the source from a syntax tree to the build log.
            Log.LogMessage(MessageImportance.High, workspace.CurrentSolution.Projects.First()
                .Documents.First(i => i.FilePath.EndsWith(".cs")).GetSyntaxRoot().GetText().ToString());

            return true;
        }
    }

    public static class IEnumerableExtension
    {
        public static string ToSingleString<T>(this IEnumerable<T> collection, string separator, string leftWrapper, string rightWrapper)
        {
            var stringBuilder = new StringBuilder();

            foreach (var item in collection)
            {
                if (stringBuilder.Length > 0)
                {
                    if (!string.IsNullOrEmpty(separator))
                        stringBuilder.Append(separator);
                }

                if (!string.IsNullOrEmpty(leftWrapper))
                    stringBuilder.Append(leftWrapper);

                stringBuilder.Append(item.ToString());

                if (!string.IsNullOrEmpty(rightWrapper))
                    stringBuilder.Append(rightWrapper);
            }

            return stringBuilder.ToString();
        }
    }
}

実際に動作することを実証するには、csproj ファイルの末尾 (終了 Project タグの直前) に次の行を追加します。ただし、プロジェクトが既に正常にビルドされており、出力フォルダーでタスク dll を見つけることができる場合に限ります。

  <Target Name="AfterBuild" DependsOnTargets="RoslynTask"/>
  <UsingTask AssemblyFile="$(OutputPath)\RoslynMsBuildTask.dll" TaskName="RoslynMsBuildTask.RoslynTask" />
  <Target Name="RoslynTask">
    <RoslynTask ReferencePath="@(ReferencePath)" Compile="@(Compile)" BaseDirectory="$(MSBuildProjectDirectory)" />
  </Target>

最初の cs ファイルのソースがビルド出力にダンプされます。


実行しようとしている分析のタイプによっては、他の csc.exe スイッチ (ConditionalDirectives、出力タイプなど) も重要になる場合があることに注意してください。このパターンを使用してタスクに渡すこともできます。MsBuild が csc.exe に渡すプロパティの完全な一覧については、$(MSBuildToolsPath)\Microsoft.CSharp.targets ファイル、CoreCompile ターゲット、Csc タスクを参照してください。

于 2013-03-11T11:16:18.237 に答える
-1

これは MSBuild の制限です。Roslyn は、ビルド中に MSBuild を再帰的に呼び出して、プロジェクトのプロパティ/ファイル/参照を確認することはできません。IProjectビルド タスク中にRoslyn を作成するには、LoadFromCommandLineArgs()代わりに メソッドを使用してみてください。CscTask が最終的にコンパイラに渡すのと同じ引数を取るように、タスクを作成する必要があります。

お役に立てれば!

于 2013-01-21T17:11:25.503 に答える