/// <summary> /// Create cil source-code representation of a <see cref="EnumDefinition"/>. /// </summary> /// <exception cref="Exceptions.InvalidAssemblyNameException"> /// Thrown when a invalid assembly name is given. /// </exception> /// <exception cref="Exceptions.InvalidNamespaceException"> /// Thrown when a invalid namespace identifier is given. /// </exception> /// <exception cref="Exceptions.OutOfBoundsValueException"> /// Thrown when enum value does not fit in given storage-type. /// </exception> /// <param name="enumDefinition">Enum to generate cil source-code for</param> /// <param name="assemblyName">Name of the assembly to generate</param> /// <param name="namespace">Optional namespace to add the enum to</param> /// <param name="headerMode">Mode to use when adding a header</param> /// <param name="indentMode">Mode to use for indenting</param> /// <param name="spaceIndentSize">When indenting with spaces this controls how many</param> /// <param name="newlineMode">Mode to use for ending lines</param> /// <param name="storageType">Underlying enum storage-type to use</param> /// <param name="curlyBracketMode">Mode to use when writing curly brackets</param> /// <returns>String containing the genenerated cil sourcecode</returns> public static string ExportCil( this EnumDefinition enumDefinition, string assemblyName, string @namespace = null, HeaderMode headerMode = HeaderMode.Default, CodeBuilder.IndentMode indentMode = CodeBuilder.IndentMode.Spaces, int spaceIndentSize = 4, CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix, StorageType storageType = StorageType.Implicit, CurlyBracketMode curlyBracketMode = CurlyBracketMode.NewLine) { if (enumDefinition == null) { throw new ArgumentNullException(nameof(enumDefinition)); } if (string.IsNullOrEmpty(assemblyName) || !IdentifierValidator.Validate(assemblyName)) { throw new InvalidAssemblyNameException(assemblyName); } if (!string.IsNullOrEmpty(@namespace) && !IdentifierValidator.ValidateNamespace(@namespace)) { throw new InvalidNamespaceException(@namespace); } foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value))) { throw new OutOfBoundsValueException(storageType, oobEntry.Value); } var builder = new CodeBuilder(indentMode, spaceIndentSize, newlineMode); if (headerMode != HeaderMode.None) { builder.AddHeader(); builder.WriteEndLine(); } // Add reference to mscorlib. builder.WriteLine(".assembly extern mscorlib { }"); builder.WriteEndLine(); // Add assembly info. builder.Write($".assembly {assemblyName}"); StartScope(builder, curlyBracketMode); builder.WriteLine(".ver 1:0:0:0"); EndScope(builder); builder.WriteEndLine(); // Add module info. builder.WriteLine($".module {assemblyName}.dll"); builder.WriteEndLine(); // Add enum class. builder.AddEnum(enumDefinition, storageType, curlyBracketMode, @namespace); return(builder.Build()); }
/// <summary> /// Create csharp source-code representation of a <see cref="EnumDefinition"/>. /// </summary> /// <exception cref="Exceptions.InvalidNamespaceException"> /// Thrown when a invalid namespace identifier is given. /// </exception> /// <exception cref="Exceptions.OutOfBoundsValueException"> /// Thrown when enum value does not fit in given storage-type. /// </exception> /// <param name="enumDefinition">Enum to generate csharp source-code for</param> /// <param name="namespace">Optional namespace to add the enum to</param> /// <param name="headerMode">Mode to use when adding a header</param> /// <param name="indentMode">Mode to use for indenting</param> /// <param name="spaceIndentSize">When indenting with spaces this controls how many</param> /// <param name="newlineMode">Mode to use for ending lines</param> /// <param name="storageType">Underlying enum storage-type to use</param> /// <param name="curlyBracketMode">Mode to use when writing curly brackets</param> /// <returns>String containing the genenerated csharp sourcecode</returns> public static string ExportCSharp( this EnumDefinition enumDefinition, string @namespace = null, HeaderMode headerMode = HeaderMode.Default, CodeBuilder.IndentMode indentMode = CodeBuilder.IndentMode.Spaces, int spaceIndentSize = 4, CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix, StorageType storageType = StorageType.Implicit, CurlyBracketMode curlyBracketMode = CurlyBracketMode.NewLine) { if (enumDefinition == null) { throw new ArgumentNullException(nameof(enumDefinition)); } if (!string.IsNullOrEmpty(@namespace) && !IdentifierValidator.ValidateNamespace(@namespace)) { throw new InvalidNamespaceException(@namespace); } foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value))) { throw new OutOfBoundsValueException(storageType, oobEntry.Value); } var builder = new CodeBuilder(indentMode, spaceIndentSize, newlineMode); if (headerMode != HeaderMode.None) { builder.AddHeader(); builder.WriteEndLine(); } builder.WriteLine("using System.CodeDom.Compiler;"); builder.WriteEndLine(); if (string.IsNullOrEmpty(@namespace)) { builder.AddEnum(enumDefinition, storageType, curlyBracketMode); } else { builder.AddNamespace( @namespace, b => b.AddEnum(enumDefinition, storageType, curlyBracketMode), curlyBracketMode); } return(builder.Build()); }
/// <summary> /// Create a pe class-library representation of a <see cref="EnumDefinition"/>. /// </summary> /// <exception cref="Exceptions.InvalidAssemblyNameException"> /// Thrown when a invalid assembly name is given. /// </exception> /// <exception cref="Exceptions.InvalidNamespaceException"> /// Thrown when a invalid namespace identifier is given. /// </exception> /// <exception cref="Exceptions.OutOfBoundsValueException"> /// Thrown when enum value does not fit in given storage-type. /// </exception> /// <param name="enumDefinition">Enum to generate a class-library for</param> /// <param name="assemblyName">Name of the assembly to generate</param> /// <param name="namespace">Optional namespace to add the enum to</param> /// <param name="storageType">Underlying enum storage-type to use</param> /// <returns>Binary pe file containing the generated class-library</returns> public static byte[] ExportClassLibrary( this EnumDefinition enumDefinition, string assemblyName, string @namespace = null, StorageType storageType = StorageType.Implicit) { if (enumDefinition == null) { throw new ArgumentNullException(nameof(enumDefinition)); } if (string.IsNullOrEmpty(assemblyName) || !IdentifierValidator.Validate(assemblyName)) { throw new InvalidAssemblyNameException(assemblyName); } if (!string.IsNullOrEmpty(@namespace) && !IdentifierValidator.ValidateNamespace(@namespace)) { throw new InvalidNamespaceException(@namespace); } foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value))) { throw new OutOfBoundsValueException(storageType, oobEntry.Value); } // Define assembly and module. using (var assemblyDefinition = AssemblyDefinition.CreateAssembly( assemblyName: new AssemblyNameDefinition(assemblyName, new Version(1, 0, 0, 0)), moduleName: $"{assemblyName}.dll", ModuleKind.Dll)) { // Set the module id to a hash of the enum-definition, this way it should be pretty // unique while still being deterministic. assemblyDefinition.MainModule.Mvid = new Guid(enumDefinition.Get128BitHash()); // Get the required references. var enumUnderlyingType = storageType.GetCecilTypeReference( typeSystem: assemblyDefinition.MainModule.TypeSystem); var enumBaseType = new TypeReference( @namespace: "System", name: "Enum", module: assemblyDefinition.MainModule, scope: assemblyDefinition.MainModule.TypeSystem.CoreLibrary); // Create type definition for the enum. var enumTypeDefinition = new TypeDefinition( @namespace, name: enumDefinition.Identifier, attributes: TypeAttributes.Public | TypeAttributes.Sealed, baseType: enumBaseType); // Add the storage field of the enum. enumTypeDefinition.Fields.Add(new FieldDefinition( name: "value__", FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, fieldType: enumUnderlyingType)); // Add the enum entries. foreach (var entry in enumDefinition.Entries) { var entryField = new FieldDefinition( name: entry.Name, attributes: FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, fieldType: enumTypeDefinition); // Set the value of the entry. entryField.Constant = storageType.Cast(entry.Value); enumTypeDefinition.Fields.Add(entryField); } // Add enum to module. assemblyDefinition.MainModule.Types.Add(enumTypeDefinition); // Write the pe dll file. using (var memoryStream = new MemoryStream()) { // Supply '0' as the timestamp to make the export deterministic. var writerParams = new WriterParameters { Timestamp = 0 }; assemblyDefinition.Write(memoryStream, writerParams); return(memoryStream.ToArray()); } } }
/// <summary> /// Create fsharp source-code representation of a <see cref="EnumDefinition"/>. /// </summary> /// <exception cref="Exceptions.InvalidNamespaceException"> /// Thrown when a invalid namespace identifier is given. /// </exception> /// <exception cref="Exceptions.OutOfBoundsValueException"> /// Thrown when enum value does not fit in given storage-type. /// </exception> /// <param name="enumDefinition">Enum to generate fsharp source-code for</param> /// <param name="namespace">Namespace to add the enum to</param> /// <param name="headerMode">Mode to use when adding a header</param> /// <param name="indentSize">How many spaces should be used for indents</param> /// <param name="newlineMode">Mode to use for ending lines</param> /// <param name="storageType">Underlying enum storage-type to use</param> /// <returns>String containing the genenerated fsharp sourcecode</returns> public static string ExportFSharp( this EnumDefinition enumDefinition, string @namespace, HeaderMode headerMode = HeaderMode.Default, int indentSize = 4, CodeBuilder.NewlineMode newlineMode = CodeBuilder.NewlineMode.Unix, StorageType storageType = StorageType.Implicit) { if (enumDefinition == null) { throw new ArgumentNullException(nameof(enumDefinition)); } if (!IdentifierValidator.ValidateNamespace(@namespace)) { throw new InvalidNamespaceException(@namespace); } foreach (var oobEntry in enumDefinition.Entries.Where(e => !storageType.Validate(e.Value))) { throw new OutOfBoundsValueException(storageType, oobEntry.Value); } var builder = new CodeBuilder(CodeBuilder.IndentMode.Spaces, indentSize, newlineMode); if (headerMode != HeaderMode.None) { builder.AddHeader(); builder.WriteEndLine(); } // Add namespace. builder.WriteLine($"namespace {@namespace}"); builder.WriteEndLine(); // Open System.CodeDom.Compiler (for the 'GeneratedCode' attribute) builder.WriteLine("open System.CodeDom.Compiler"); builder.WriteEndLine(); // Add type comment. if (!string.IsNullOrEmpty(enumDefinition.Comment)) { builder.AddSummary(enumDefinition.Comment); } // Add enum definition. var assemblyName = typeof(FSharpExporter).Assembly.GetName(); builder.WriteLine($"[<GeneratedCode(\"{assemblyName.Name}\", \"{assemblyName.Version}\")>]"); builder.WriteLine($"type {enumDefinition.Identifier} ="); // Add entries. foreach (var entry in enumDefinition.Entries) { var literalSuffix = storageType == StorageType.Implicit ? string.Empty : storageType.GetFSharpLiteralSuffix(); builder.WriteLine($"| {entry.Name} = {entry.Value}{literalSuffix}", additionalIndent: 1); } return(builder.Build()); }