Рослин не имеет никакого отношения к System.Runtime
Я работаю над проектом, в котором мы используем Roslyn для составления некоторых шаблонов для нас. Теперь, когда я компилирую шаблон, я получаю несколько ошибок в CompileResult.Diagnostics
,
Ошибки:
(21,6): error CS0012: The type 'System.Attribute' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
(21,6): error CS0012: The type 'System.Type' is defined in an assembly that is not referenced. You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.
Видя эти ошибки, я предположил, что не добавил ссылку на System.Runtime
сборка правильно. Тем не менее, после проверки загруженных сборок, это, кажется, в порядке.
private IEnumerable<MetadataReference> GetGlobalReferences()
{
var assemblies = new []
{
typeof(System.Object).Assembly, //mscorlib
typeof(System.Composition.ExportAttribute).Assembly, //System.Composition (MEF)
typeof(System.CodeDom.Compiler.CodeCompiler).Assembly, //System.CodeDom.Compiler
};
var refs = from a in assemblies
select new MetadataFileReference(a.Location);
return refs.ToList();
}
И сама компиляция:
public void Compile(AssemblyFileInfo assemblyInfo)
{
Parse(assemblyInfo.Files);
var compilation = CSharpCompilation.Create(assemblyInfo.FilePath, options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.AddReferences(GetGlobalReferences())
.AddSyntaxTrees(assemblyInfo.SourceCodeSyntaxTrees);
assemblyInfo.CompileResult = compilation.Emit(assemblyInfo.FilePath);
}
Я что-то упускаю из виду? Похоже, все предпосылки для успешной компиляции выполнены, но, по-видимому, они не выполнены.
Для справки: это (обфусцированный) фрагмент кода, который я пытаюсь скомпилировать:
namespace Project.Rules.Generated
{
using System;
using System.Runtime;
using System.Composition;
using System.CodeDom.Compiler;
[Export(typeof(IProject))]
[GeneratedCode("Project Template Compiler", "1.0")]
public sealed class ProcessPriorityValue : ProjectConcreteClass
{
public override void Execute(ProjectExecutionContext ctx)
{
CurrentContext = ctx;
}
}
}
Я немного продвинулся в своих поисках. PublicKeyToken, указанный в сообщениях об ошибках, соответствует PublicKeyToken сборок System.Composition. Я думаю, что добавление всех сборок может решить проблему. Это правильно, или, по крайней мере, часть решения. Используя dotPeek, я смог проверить, какие объекты существуют в разных сборках. С этим знанием я изменил GetGlobalReferences()
метод к этому:
private IEnumerable<MetadataReference> GetGlobalReferences()
{
var assemblies = new []
{
typeof(System.Object).Assembly, //mscorlib
typeof(System.Composition.ExportAttribute).Assembly, //System.Composition.AttributeModel
typeof(System.Composition.Convention.ConventionBuilder).Assembly, //System.Composition.Convention
typeof(System.Composition.Hosting.CompositionHost).Assembly, //System.Composition.Hosting
typeof(System.Composition.CompositionContext).Assembly, //System.Composition.Runtime
typeof(System.Composition.CompositionContextExtensions).Assembly, //System.Composition.TypedParts
typeof(System.CodeDom.Compiler.CodeCompiler).Assembly, //System.CodeDom.Compiler
};
var refs = from a in assemblies
select new MetadataFileReference(a.Location);
return refs.ToList();
}
Как видите, теперь я добавляю все сборки System.Composition, указав объект, который существует в сборке. Добавляя System.Composition.Runtime
Мои ошибки компиляции были решены.
Это внесло другую ошибку, хотя. Как вы можете проверить сами, в универсальном классе экспорта есть System.Composition.Runtime
: public sealed class Export<T> : IDisposable
Из-за этого я теперь получаю эту ошибку:
(21,6): error CS0404: Cannot apply attribute class 'System.Composition.Export<T>' because it is generic
По какой-то причине код сейчас хочет использовать System.Composition.Runtime.Export<T>
а не ExportAttribute, определенный в System.Composition.AttributeModel
сборка.
edit2
Я могу подтвердить, что приведенный выше код использует System.Composition.Export<T>
а не ExportAttribute
, Я обнаружил это, изменив [Export(typeof(IProject)]
в [ExportAttribute(typeof(IProject)]
, Из-за этого изменения вернулись исходные ошибки. Похоже на сборку System.Composition.AttributeModel
не загружается / ссылается правильно, но после проверки compilation
Я вижу, что сборка ссылается хорошо.
Ссылочные сборки, которые я получил на данный момент:
+ [0] mscorlib, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity
+ [1] System.Composition.AttributedModel, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity
+ [2] System.Composition.Convention, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity
+ [3] System.Composition.Hosting, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity
+ [4] System.Composition.Runtime, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity
+ [5] System.Composition.TypedParts, Version=1.0.20.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity
+ [6] Microsoft.CSharp, Version=4.0.0.0, Culture=neutral, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293 Microsoft.CodeAnalysis.AssemblyIdentity
+ [7] System, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity
+ [8] System.Core, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity
+ [9] System.Data, Version=4.0.0.0, Culture=neutral, PublicKey=00000000000000000400000000000000 Microsoft.CodeAnalysis.AssemblyIdentity
3 ответа
По запросу Деяна в разделе комментариев я выложу ответ (на мою проблему) как реальный ответ.
Я выяснил, в чем проблема! Компилятор был верен все время. Сообщение в блоге smack0007 меня попробовать что-то еще. Вместо того, чтобы использовать Фасадную DLL, попробуйте ссылаться на необходимые DLL вручную. GetGlobalReferences
метод теперь выглядит так:
private IEnumerable<MetadataReference> GetGlobalReferences()
{
var assemblies = new []
{
/*Making sure all MEF assemblies are loaded*/
typeof(System.Composition.Convention.AttributedModelProvider).Assembly, //System.Composition.AttributeModel
typeof(System.Composition.Convention.ConventionBuilder).Assembly, //System.Composition.Convention
typeof(System.Composition.Hosting.CompositionHost).Assembly, //System.Composition.Hosting
typeof(System.Composition.CompositionContext).Assembly, //System.Composition.Runtime
typeof(System.Composition.CompositionContextExtensions).Assembly, //System.Composition.TypedParts
/*Used for the GeneratedCode attribute*/
typeof(System.CodeDom.Compiler.CodeCompiler).Assembly, //System.CodeDom.Compiler
};
var refs = from a in assemblies
select new MetadataFileReference(a.Location);
var returnList = refs.ToList();
//The location of the .NET assemblies
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
/*
* Adding some necessary .NET assemblies
* These assemblies couldn't be loaded correctly via the same construction as above,
* in specific the System.Runtime.
*/
returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "mscorlib.dll")));
returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "System.dll")));
returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "System.Core.dll")));
returnList.Add(new MetadataFileReference(Path.Combine(assemblyPath, "System.Runtime.dll")));
return returnList;
}
При декомпиляции System.Runtime.dll
Я также понял, почему на него нельзя ссылаться каким-либо другим способом. DLL пуста, она содержит только некоторые ссылки на другие сборки. Поэтому нельзя ссылаться на эту сборку иначе.
Похоже, что вы ссылаетесь на PortableClassLibrary. Портативные библиотеки классов выбирают некоторые из основных типов (например, объект / строка / и т. Д.) Из "System.Runtime.dll". Тем не менее, в настольных системах они взяты из mscorlib.dll. Когда вы используете typeof(object).Assembly
, ты получаешь собственную версию Рослина object
, Поскольку Roslyn не создан как Portable Class Libraries, он принадлежит mscorlib и не соответствует идентичности других ваших ссылок.
Предустановленный список ссылок у меня не работал.
Но получать их отAppDomain
помогло:
public static readonly List<PortableExecutableReference> References =
AppDomain.CurrentDomain.GetAssemblies()
.Where(_ => !_.IsDynamic && !string.IsNullOrWhiteSpace(_.Location))
.Select(_ => MetadataReference.CreateFromFile(_.Location))
.Concat(new[]
{
// add your app/lib specifics, e.g.:
MetadataReference.CreateFromFile(typeof(MyType).Assembly.Location),
})
.ToList();
Я нашел ответ в этом полезном репо: https://github.com/andrewlock/NetEscapades.EnumGenerators .