如何使Roslyn编译复制引用

时间:2015-08-01 20:10:47

标签: c# roslyn

使用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等添加引用(以自动方式),而不需要循环引用和做我自己

2 个答案:

答案 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);
    }