As input for compilation I have a string with the following code in it:
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
public string EmailAddress { get; set; }
}
I have the following code, note the comment at [01]
. The intent here is to take a string that contains a class (from this.Source
and emit the code for the assembly into a MemoryStream
.
var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
var assemblyName = Guid.NewGuid().ToString();
var syntaxTrees = CSharpSyntaxTree.ParseText(this.Source);
// build references up
var references = new List<MetadataReference>();
//[01] references.Add("System.dll"));
// set up compilation
var compilation = CSharpCompilation.Create(assemblyName)
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
.AddReferences(references)
.AddSyntaxTrees(syntaxTrees);
// build the assembly
Assembly assembly;
using (var stream = new MemoryStream())
{
// this is broked...
EmitResult compileResult = compilation.Emit(stream);
// [02] we get here, with diagnostic errors (check compileResult.Diagnostics)
assembly = Assembly.Load(stream.GetBuffer());
}
At [02]
I am getting a BadImageFormat
exception, with the following in compileResult.Diagnostics:
[0]: warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
[1]: (2,18): error CS0518: Predefined type 'System.Object' is not defined or imported
[2]: (4,16): error CS0518: Predefined type 'System.String' is not defined or imported
[3]: (4,40): error CS0518: Predefined type 'System.Void' is not defined or imported
[4]: (5,16): error CS0518: Predefined type 'System.String' is not defined or imported
[5]: (5,39): error CS0518: Predefined type 'System.Void' is not defined or imported
[6]: (6,16): error CS0518: Predefined type 'System.Int32' is not defined or imported
[7]: (6,31): error CS0518: Predefined type 'System.Void' is not defined or imported
[8]: (7,16): error CS0518: Predefined type 'System.String' is not defined or imported
[9]: (7,43): error CS0518: Predefined type 'System.Void' is not defined or imported
[10]: (2,18): error CS1729: 'object' does not contain a constructor that takes 0 arguments
If I add a using System;
to the start of the code I get the following error:
error CS0246: The type or namespace name 'System' could not be found (are you missing a using directive or an assembly reference?)
That leads me to believe that I don't have access to System from where I sit, which is why I stubbed in that pseudo-code references.Add("System.dll"));
. It's obviously incorrect, but it's my intent.
For a little further information, the intent here is to then create an instance of the generated type dynamically and assign values to the properties.
What is the correct way to make references available to the compiler?
Or, is there another approach for compiling a class like this (from a string input)?
Call the AssemblyMetadata.CreateFromFile(path)
method, and pass typeof(object).Assembly.Location
(or other assemblies).
For .net core you can use
public static class TrustedPlatformAssembly
{
public static string From( string shortDllName )
{
string dllString = AppContext.GetData( "TRUSTED_PLATFORM_ASSEMBLIES" ).ToString();
var dlls = dllString.Split( ";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries );
string dll = dlls.Single( d => d.Contains( shortDllName, StringComparison.OrdinalIgnoreCase ) );
return dll;
}
}
I used it like this:
public IEnumerable<string> GetDllsToReference()
{
// add a big pile of .net dlls, all using AppContext.GetData( "TRUSTED_PLATFORM_ASSEMBLIES" )
List<string> dllsToReturn = new List<string>()
{
"mscorlib.dll",
"system.runtime.dll",
"system.private.corelib.dll",
"netstandard.dll",
"System.Text.RegularExpressions.dll",
"system.linq.dll",
"system.net.dll",
"system.data.dll",
"System.Collections.dll",
"System.IO.dll",
"System.IO.FileSystem.dll",
"System.Runtime.Extensions.dll",
"System.Windows.Forms.dll",
"UIAutomationClient.dll",
"UIAutomationTypes.dll",
"Accessibility.dll",
"System.Configuration.ConfigurationManager.dll",
"PresentationFramework.dll",
"PresentationCore.dll",
"System.CodeDom.dll",
"System.Drawing.Common.dll",
"System.Windows.Controls.Ribbon.dll",
"WindowsFormsIntegration.dll",
"System.Xaml.dll",
"System.IO.Packaging.dll",
"System.Xml.XmlSerializer.dll",
"System.Xml.XDocument.dll",
"System.Xml.ReaderWriter.dll",
"System.Private.Xml.dll",
"System.Private.Xml.Linq",
"System.Private.Uri.dll",
"System.Diagnostics.Process.dll",
"System.Drawing.Primitives.dll",
"System.Data.Common.dll",
"System.ComponentModel.Primitives.dll",
"Microsoft.VisualBasic.Core.dll",
"System.ComponentModel.TypeConverter.dll",
"System.Linq.Expressions.dll",
"System.ObjectModel.dll",
"System.Diagnostics.Tools.dll",
"System.Net.Http.dll",
"System.ComponentModel.dll",
"Microsoft.Win32.Primitives.dll",
"System.Collections.Specialized.dll",
"System.Collections.NonGeneric.dll",
"System.Diagnostics.FileVersionInfo.dll",
"System.Resources.ResourceManager.dll",
"System.Net.Requests.dll",
"System.Net.Mail.dll",
"System.Linq.Parallel.dll",
"System.Net.Primitives.dll",
"System.Resources.Writer.dll",
"System.Collections.Concurrent.dll",
"System.Collections.Immutable.dll",
"System.Security.Claims.dll",
"System.Console.dll",
"System.Web.HttpUtility.dll",
"System.Runtime.InteropServices.dll",
"System.Threading.Tasks.Parallel.dll",
"WindowsBase.dll",
"Microsoft.Win32.Registry.dll",
"System.Security.Principal.Windows.dll",
};
foreach ( var dll in dllsToReturn )
{
yield return TrustedPlatformAssembly.From( dll );
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With