使用Roslyn编译项目时,一切正常,但由于项目引用其他程序集,我需要将它们复制到输出目录
我有这段代码:
var workspace = MSBuildWorkspace.Create();
var projects = workspace.OpenSolutionAsync(@"Solution.sln").Result;
var project = projects.Projects.First();
var compilation = project.GetCompilationAsync().Result;
var dllPath = Path.Combine(Directory.GetCurrentDirectory(), "Example.dll");
var pdbPath = Path.Combine(Directory.GetCurrentDirectory(), "Example.pdb");
using (FileStream dllStream = new FileStream(dllPath, FileMode.OpenOrCreate))
using (FileStream pdbStream = new FileStream(pdbPath, FileMode.OpenOrCreate))
{
var emit = compilation.Emit(dllStream, pdbStream);
}
var assembly = Assembly.LoadFile(dllPath);
当然它只写了Example.dll,但是我没有找到告诉编译的选项或者发出使用CopyLocal等添加引用(以自动方式),而不需要循环引用和做我自己
答案 0 :(得分:4)
Roslyn绝不会复制引用。这不是编译器所做的事情。在常规构建中,MSBuild决定是否在本地复制引用。
如果您希望复制引用,那么您的代码需要处理这些引用。
答案 1 :(得分:0)
罗斯林不会复制参考文献。 正如@Kevin Pilch所说,这不是编译器的责任。
我认为,MSBuildWorkspace
之类的东西应该具有这些知识,即使它没有对它采取行动。
这是project.FilePath
的快速修复,解析文件。
private static IEnumerable<PortableExecutableReference> GetMetadataReferencesToCopy(string path, IEnumerable<MetadataReference> metadataReferences)
{
var references = metadataReferences
.OfType<PortableExecutableReference>()
.Select(x => new
{
Name = Path.GetFileNameWithoutExtension(x.FilePath),
Reference = x,
})
.ToDictionary(x => x.Name, x => x.Reference);
var xmldoc = new XmlDocument();
xmldoc.Load(path);
foreach (XmlNode item in xmldoc.GetElementsByTagName("Reference"))
{
var include = item.Attributes?
.OfType<XmlAttribute>()
.FirstOrDefault(x => x.Name == "Include")?
.Value;
if (include == null)
{
continue;
}
var name = new AssemblyName(include).Name;
bool copyLocal;
if (bool.TryParse(item.ChildNodes?
.OfType<XmlNode>()
.FirstOrDefault(x => x.Name == "Private")?
.InnerText, out copyLocal) &&
references.ContainsKey(name) &&
copyLocal)
{
yield return references[name];
}
}
}
您可以这样称呼它:
var metadataReferences = GetMetadataReferencesToCopy(project.FilePath, project.MetadataReferences);
foreach (var item in metadataReferences)
{
Console.WriteLine(item.FilePath);
}