Я пишу экстрактор метаданных для проектов С#. Он работает, создавая SyntaxTrees
из исходных файлов через CSharpSyntaxTree.ParseText()
, компилируя их через CSharpCompilation.Create()
и затем анализируя символы в файле SemanticModel
.
Я столкнулся с проблемой, когда различные ссылки на сборки обрабатываются неправильно.
Я генерирую ссылки на сборки, анализируя project.assets.json
и извлекая ссылки на пакеты времени компиляции (мой тестовый проект не содержит ссылок на проекты). Целевой раздел project.assets.json
выглядит так:
"targets": {
".NETStandard,Version=v2.1": {
"Autofac/5.1.2": {
"type": "package",
"compile": {
"lib/netstandard2.1/Autofac.dll": {}
},
"runtime": {
"lib/netstandard2.1/Autofac.dll": {}
}
},
"Microsoft.NETCore.Platforms/1.1.0": {
"type": "package",
"compile": {
"lib/netstandard1.0/_._": {}
},
"runtime": {
"lib/netstandard1.0/_._": {}
}
},
"Microsoft.NETCore.Targets/1.1.0": {
"type": "package",
"compile": {
"lib/netstandard1.0/_._": {}
},
"runtime": {
"lib/netstandard1.0/_._": {}
}
},
"Serilog/2.9.0": {
"type": "package",
"compile": {
"lib/netstandard2.0/Serilog.dll": {}
},
"runtime": {
"lib/netstandard2.0/Serilog.dll": {}
}
},
"Serilog.Sinks.Console/3.1.1": {
"type": "package",
"dependencies": {
"Serilog": "2.5.0",
"System.Console": "4.3.0"
},
"compile": {
"lib/netstandard1.3/Serilog.Sinks.Console.dll": {}
},
"runtime": {
"lib/netstandard1.3/Serilog.Sinks.Console.dll": {}
}
},
"Serilog.Sinks.File/4.1.0": {
"type": "package",
"dependencies": {
"Serilog": "2.5.0",
"System.IO.FileSystem": "4.0.1",
"System.Text.Encoding.Extensions": "4.0.11",
"System.Threading.Timer": "4.0.1"
},
"compile": {
"lib/netstandard2.0/Serilog.Sinks.File.dll": {}
},
"runtime": {
"lib/netstandard2.0/Serilog.Sinks.File.dll": {}
}
},
"System.Console/4.3.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.IO": "4.3.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0"
},
"compile": {
"ref/netstandard1.3/System.Console.dll": {}
}
},
"System.IO/4.3.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0",
"System.Text.Encoding": "4.3.0",
"System.Threading.Tasks": "4.3.0"
},
"compile": {
"ref/netstandard1.5/System.IO.dll": {}
}
},
"System.IO.FileSystem/4.0.1": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Targets": "1.0.1",
"System.IO": "4.1.0",
"System.IO.FileSystem.Primitives": "4.0.1",
"System.Runtime": "4.1.0",
"System.Runtime.Handles": "4.0.1",
"System.Text.Encoding": "4.0.11",
"System.Threading.Tasks": "4.0.11"
},
"compile": {
"ref/netstandard1.3/System.IO.FileSystem.dll": {}
}
},
"System.IO.FileSystem.Primitives/4.0.1": {
"type": "package",
"dependencies": {
"System.Runtime": "4.1.0"
},
"compile": {
"ref/netstandard1.3/System.IO.FileSystem.Primitives.dll": {}
},
"runtime": {
"lib/netstandard1.3/System.IO.FileSystem.Primitives.dll": {}
}
},
"System.Runtime/4.3.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0"
},
"compile": {
"ref/netstandard1.5/System.Runtime.dll": {}
}
},
"System.Runtime.Handles/4.0.1": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Targets": "1.0.1",
"System.Runtime": "4.1.0"
},
"compile": {
"ref/netstandard1.3/System.Runtime.Handles.dll": {}
}
},
"System.Text.Encoding/4.3.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
},
"compile": {
"ref/netstandard1.3/System.Text.Encoding.dll": {}
}
},
"System.Text.Encoding.Extensions/4.0.11": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Targets": "1.0.1",
"System.Runtime": "4.1.0",
"System.Text.Encoding": "4.0.11"
},
"compile": {
"ref/netstandard1.3/System.Text.Encoding.Extensions.dll": {}
}
},
"System.Threading.Tasks/4.3.0": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.1.0",
"Microsoft.NETCore.Targets": "1.1.0",
"System.Runtime": "4.3.0"
},
"compile": {
"ref/netstandard1.3/System.Threading.Tasks.dll": {}
}
},
"System.Threading.Timer/4.0.1": {
"type": "package",
"dependencies": {
"Microsoft.NETCore.Platforms": "1.0.1",
"Microsoft.NETCore.Targets": "1.0.1",
"System.Runtime": "4.1.0"
},
"compile": {
"ref/netstandard1.2/System.Threading.Timer.dll": {}
}
}
}
}
В результате список литературы выглядит следующим образом:
lib/netstandard2.1/Autofac.dll
lib/netstandard1.0/_._
lib/netstandard1.0/_._
lib/netstandard2.0/Serilog.dll
lib/netstandard1.3/Serilog.Sinks.Console.dll
lib/netstandard2.0/Serilog.Sinks.File.dll
ref/netstandard1.3/System.Console.dll
ref/netstandard1.5/System.IO.dll
ref/netstandard1.3/System.IO.FileSystem.dll
ref/netstandard1.3/System.IO.FileSystem.Primitives.dll
ref/netstandard1.5/System.Runtime.dll
ref/netstandard1.3/System.Runtime.Handles.dll
ref/netstandard1.3/System.Text.Encoding.dll
ref/netstandard1.3/System.Text.Encoding.Extensions.dll
ref/netstandard1.3/System.Threading.Tasks.dll
ref/netstandard1.2/System.Threading.Timer.dll
Я игнорирую два странного формата netstandard1.0, заменяя их ссылкой, созданной MetadataReference.CreateFromFile( Assembly.Load( "netstandard" ).Location ) )
, и разрешаю оставшиеся пути для локальных репозиториев nuget, создавая ссылки из dll.
В основном это работает нормально... но некоторые вещи не решаются. Вот диагностические сообщения, которые я получаю после компиляции с CSharpCompilation.Create()
:
CS0103 — Имя «Сборка» не существует в текущем контексте.
CS0103 — Имя «Путь» не существует в текущем контексте.
CS1069 — Не удалось найти имя типа «ApplicationException» в пространстве имен «Система». Этот тип был перенаправлен в сборку «System.Runtime, версия = 4.1.0.0, культура = нейтральная, PublicKeyToken = b03f5f7f11d50a3a». Рассмотрите возможность добавления ссылки на эту сборку. SymbolExtractor:: АнализеПрожект
CS0103 — Имя «Среда» не существует в текущем контексте.
Интересно, что все эти ошибки относятся к одному методу статического класса в проекте, который я пытаюсь скомпилировать. Я не уверен, что это актуально, но вот этот код:
public static string DefineLocalAppDataLogPath( string fileStub, string folder = null )
{
fileStub = IsFileNameValid( fileStub ) ? fileStub : "log.txt";
if( string.IsNullOrEmpty( folder ) )
{
var assLoc = Assembly.GetExecutingAssembly().GetType().Assembly.Location;
folder = Path.GetFileNameWithoutExtension( assLoc );
}
DirectoryInfo logDir = null;
if( ( logDir = CreateLogFileDirectory( folder ) ) == null )
{
if( ( logDir = CreateLogFileDirectory( "LogFiles" ) ) == null )
throw new ApplicationException(
$"Couldn't create log file directory {folder} or the backup/default directory 'LogFiles'" );
}
return logDir.FullName;
}
Что мне не хватает в разрешении зависимостей сборки? Нужно ли также включать ссылки на сборки, необходимые во время выполнения?