/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Collections.Generic; namespace dnSpy.Debugger.DotNet.Metadata { /// /// A .NET AppDomain /// public abstract class DmdAppDomain : DmdObject { /// /// Dummy abstract method to make sure no-one outside this assembly can create their own /// private protected abstract void YouCantDeriveFromThisClass(); /// /// Gets the runtime /// public abstract DmdRuntime Runtime { get; } /// /// Gets the unique AppDomain id /// public abstract int Id { get; } /// /// Creates an assembly and adds it to the AppDomain. The first created assembly must be the corlib () /// /// Called to provide the metadata /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// public DmdAssembly CreateAssembly(Func getMetadata, bool isInMemory, bool isDynamic, string fullyQualifiedName, string assemblyLocation) => CreateAssembly(getMetadata, isInMemory, isDynamic, fullyQualifiedName, assemblyLocation, assemblySimpleName: null, isSynthetic: false, addAssembly: true); /// /// Creates a synthetic assembly but does not add it to the AppDomain /// /// Called to provide the metadata /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// The assembly's simple name or null if it's unknown /// public DmdAssembly CreateSyntheticAssembly(Func getMetadata, bool isInMemory, bool isDynamic, string fullyQualifiedName, string assemblyLocation, string? assemblySimpleName) => CreateAssembly(getMetadata, isInMemory, isDynamic, fullyQualifiedName, assemblyLocation, assemblySimpleName: assemblySimpleName, isSynthetic: true, addAssembly: false); /// /// Creates an assembly and optionally adds it to the AppDomain. The first created assembly must be the corlib () /// /// Called to provide the metadata /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// The assembly's simple name or null if it's unknown /// true if it's a synthetic assembly; it's not loaded in the debugged process /// true if the assembly should be added to the AppDomain /// public DmdAssembly CreateAssembly(Func getMetadata, bool isInMemory, bool isDynamic, string fullyQualifiedName, string assemblyLocation, string? assemblySimpleName, bool isSynthetic, bool addAssembly) => CreateAssembly(getMetadata, new DmdCreateAssemblyInfo(isInMemory, isDynamic, isSynthetic, addAssembly, fullyQualifiedName, assemblyLocation, assemblySimpleName)); /// /// Creates an assembly and optionally adds it to the AppDomain. The first created assembly must be the corlib () /// /// Called to provide the metadata /// Assembly info /// public abstract DmdAssembly CreateAssembly(Func getMetadata, DmdCreateAssemblyInfo assemblyInfo); /// /// Creates an assembly. The first created assembly must be the corlib () /// /// Filename /// true if file layout, false if memory layout /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// public DmdAssembly CreateAssembly(string filename, bool isFileLayout = true, bool isInMemory = false, bool isDynamic = false, string? fullyQualifiedName = null, string? assemblyLocation = null) { if (filename is null) throw new ArgumentNullException(nameof(filename)); return CreateAssembly(() => new DmdLazyMetadataBytesFile(filename, isFileLayout), isInMemory, isDynamic, fullyQualifiedName ?? filename, assemblyLocation ?? filename); } /// /// Creates an assembly. The first created assembly must be the corlib () /// /// Address of PE file /// Size of PE file /// true if file layout, false if memory layout /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// public DmdAssembly CreateAssembly(IntPtr address, uint size, bool isFileLayout, bool isInMemory, bool isDynamic, string fullyQualifiedName, string assemblyLocation) => CreateAssembly(() => new DmdLazyMetadataBytesPtr(address, size, isFileLayout), isInMemory, isDynamic, fullyQualifiedName, assemblyLocation); /// /// Creates an assembly. The first created assembly must be the corlib () /// /// Raw PE file bytes /// true if file layout, false if memory layout /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// public DmdAssembly CreateAssembly(byte[] assemblyBytes, bool isFileLayout, bool isInMemory, bool isDynamic, string fullyQualifiedName, string assemblyLocation) { if (assemblyBytes is null) throw new ArgumentNullException(nameof(assemblyBytes)); return CreateAssembly(() => new DmdLazyMetadataBytesArray(assemblyBytes, isFileLayout), isInMemory, isDynamic, fullyQualifiedName, assemblyLocation); } /// /// Creates an assembly. The first created assembly must be the corlib () /// /// COM IMetaDataImport instance /// Helper class /// Dispatcher to use when accessing /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// public DmdAssembly CreateAssembly(object comMetadata, DmdDynamicModuleHelper dynamicModuleHelper, DmdDispatcher dispatcher, bool isInMemory, bool isDynamic, string fullyQualifiedName, string? assemblyLocation = null) { if (comMetadata is null) throw new ArgumentNullException(nameof(comMetadata)); if (dynamicModuleHelper is null) throw new ArgumentNullException(nameof(dynamicModuleHelper)); if (dispatcher is null) throw new ArgumentNullException(nameof(dispatcher)); var mdi = comMetadata as Impl.COMD.IMetaDataImport2 ?? throw new ArgumentException("Only IMetaDataImport is supported"); return CreateAssembly(() => new DmdLazyMetadataBytesCom(mdi, dynamicModuleHelper, dispatcher), isInMemory, isDynamic, fullyQualifiedName, assemblyLocation ?? string.Empty); } /// /// Adds a module to an existing assembly /// /// Assembly /// Called to provide the metadata /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// public abstract DmdModule CreateModule(DmdAssembly assembly, Func getMetadata, bool isInMemory, bool isDynamic, string fullyQualifiedName); /// /// Adds a module to an existing assembly /// /// Assembly /// Filename /// true if file layout, false if memory layout /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// public DmdModule CreateModule(DmdAssembly assembly, string filename, bool isFileLayout = true, bool isInMemory = false, bool isDynamic = false, string? fullyQualifiedName = null) { if (filename is null) throw new ArgumentNullException(nameof(filename)); return CreateModule(assembly, () => new DmdLazyMetadataBytesFile(filename, isFileLayout), isInMemory, isDynamic, fullyQualifiedName ?? filename); } /// /// Adds a module to an existing assembly /// /// Assembly /// Address of the PE file /// Size of the PE file /// true if file layout, false if memory layout /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// public DmdModule CreateModule(DmdAssembly assembly, IntPtr address, uint size, bool isFileLayout, bool isInMemory, bool isDynamic, string fullyQualifiedName) => CreateModule(assembly, () => new DmdLazyMetadataBytesPtr(address, size, isFileLayout), isInMemory, isDynamic, fullyQualifiedName); /// /// Adds a module to an existing assembly /// /// Assembly /// Raw PE file bytes /// true if file layout, false if memory layout /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// public DmdModule CreateModule(DmdAssembly assembly, byte[] moduleBytes, bool isFileLayout, bool isInMemory, bool isDynamic, string fullyQualifiedName) { if (moduleBytes is null) throw new ArgumentNullException(nameof(moduleBytes)); return CreateModule(assembly, () => new DmdLazyMetadataBytesArray(moduleBytes, isFileLayout), isInMemory, isDynamic, fullyQualifiedName); } /// /// Adds a module to an existing assembly /// /// Assembly /// COM IMetaDataImport instance /// Helper class /// Dispatcher to use when accessing /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// The fully qualified name of the module (). See /// public DmdModule CreateModule(DmdAssembly assembly, object comMetadata, DmdDynamicModuleHelper dynamicModuleHelper, DmdDispatcher dispatcher, bool isInMemory, bool isDynamic, string fullyQualifiedName) { if (comMetadata is null) throw new ArgumentNullException(nameof(comMetadata)); if (dynamicModuleHelper is null) throw new ArgumentNullException(nameof(dynamicModuleHelper)); if (dispatcher is null) throw new ArgumentNullException(nameof(dispatcher)); var mdi = comMetadata as Impl.COMD.IMetaDataImport2 ?? throw new ArgumentException("Only IMetaDataImport is supported"); return CreateModule(assembly, () => new DmdLazyMetadataBytesCom(mdi, dynamicModuleHelper, dispatcher), isInMemory, isDynamic, fullyQualifiedName); } /// /// Adds an assembly /// /// Assembly to add public abstract void Add(DmdAssembly assembly); /// /// Removes an assembly /// /// Assembly to remove public abstract void Remove(DmdAssembly assembly); /// /// Adds an assembly. It gets removed when the return value's method gets called /// /// Assembly to add /// public TemporaryAssemblyDisposable AddTemporaryAssembly(DmdAssembly assembly) => new TemporaryAssemblyDisposable(assembly); /// /// Adds and removes an assembly /// public readonly struct TemporaryAssemblyDisposable : IDisposable { readonly DmdAssembly assembly; internal TemporaryAssemblyDisposable(DmdAssembly assembly) { this.assembly = assembly ?? throw new ArgumentNullException(nameof(assembly)); assembly.AppDomain.Add(assembly); } /// /// Dispose() /// public void Dispose() => assembly.AppDomain.Remove(assembly); } /// /// Gets all assemblies /// /// public DmdAssembly[] GetAssemblies() => GetAssemblies(includeSyntheticAssemblies: true); /// /// Gets all assemblies /// /// true to include synthetic assemblies /// public abstract DmdAssembly[] GetAssemblies(bool includeSyntheticAssemblies); /// /// Gets an assembly or returns null if there's no such assembly /// /// Simple name of the assembly, eg. "System" /// public abstract DmdAssembly? GetAssembly(string simpleName); /// /// Gets an assembly or returns null if there's no such assembly /// /// Assembly name /// public abstract DmdAssembly? GetAssembly(IDmdAssemblyName name); /// /// Loads an assembly /// /// Evaluation context /// Full assembly name /// public DmdAssembly? Load(object? context, string assemblyName) => Load(context, new DmdReadOnlyAssemblyName(assemblyName)); /// /// Loads an assembly /// /// Evaluation context /// Assembly name /// public abstract DmdAssembly? Load(object? context, IDmdAssemblyName name); /// /// Loads an assembly. Will fail on .NET Core 1.x (but not on .NET Core 2.x or later) /// /// Evaluation context /// Assembly name or path to assembly /// public abstract DmdAssembly? LoadFrom(object? context, string assemblyFile); /// /// Loads an assembly. Will fail on .NET Core 1.x (but not on .NET Core 2.x or later) /// /// Evaluation context /// Path to assembly /// public abstract DmdAssembly? LoadFile(object? context, string path); /// /// Gets the core library (eg. mscorlib if it's .NET Framework) /// public abstract DmdAssembly? CorLib { get; } /// /// Checks if a well known type exists in one of the loaded assemblies /// /// Well known type /// public bool HasWellKnownType(DmdWellKnownType wellKnownType) => GetWellKnownType(wellKnownType, isOptional: true) is not null; /// /// Gets a well known type /// /// Well known type /// public DmdType GetWellKnownType(DmdWellKnownType wellKnownType) => GetWellKnownType(wellKnownType, isOptional: false)!; /// /// Gets a well known type /// /// Well known type /// Used if the type couldn't be found. If true, null is returned, and if false, an exception is thrown /// public DmdType? GetWellKnownType(DmdWellKnownType wellKnownType, bool isOptional) => GetWellKnownType(wellKnownType, isOptional, onlyCorlib: false); internal abstract DmdType? GetWellKnownType(DmdWellKnownType wellKnownType, bool isOptional, bool onlyCorlib); #pragma warning disable CS1591 // Missing XML comment for publicly visible type or member public DmdType System_Object => GetWellKnownType(DmdWellKnownType.System_Object); public DmdType System_Enum => GetWellKnownType(DmdWellKnownType.System_Enum); public DmdType System_MulticastDelegate => GetWellKnownType(DmdWellKnownType.System_MulticastDelegate); public DmdType System_Delegate => GetWellKnownType(DmdWellKnownType.System_Delegate); public DmdType System_ValueType => GetWellKnownType(DmdWellKnownType.System_ValueType); public DmdType System_Void => GetWellKnownType(DmdWellKnownType.System_Void); public DmdType System_Boolean => GetWellKnownType(DmdWellKnownType.System_Boolean); public DmdType System_Char => GetWellKnownType(DmdWellKnownType.System_Char); public DmdType System_SByte => GetWellKnownType(DmdWellKnownType.System_SByte); public DmdType System_Byte => GetWellKnownType(DmdWellKnownType.System_Byte); public DmdType System_Int16 => GetWellKnownType(DmdWellKnownType.System_Int16); public DmdType System_UInt16 => GetWellKnownType(DmdWellKnownType.System_UInt16); public DmdType System_Int32 => GetWellKnownType(DmdWellKnownType.System_Int32); public DmdType System_UInt32 => GetWellKnownType(DmdWellKnownType.System_UInt32); public DmdType System_Int64 => GetWellKnownType(DmdWellKnownType.System_Int64); public DmdType System_UInt64 => GetWellKnownType(DmdWellKnownType.System_UInt64); public DmdType System_Decimal => GetWellKnownType(DmdWellKnownType.System_Decimal); public DmdType System_Single => GetWellKnownType(DmdWellKnownType.System_Single); public DmdType System_Double => GetWellKnownType(DmdWellKnownType.System_Double); public DmdType System_String => GetWellKnownType(DmdWellKnownType.System_String); public DmdType System_IntPtr => GetWellKnownType(DmdWellKnownType.System_IntPtr); public DmdType System_UIntPtr => GetWellKnownType(DmdWellKnownType.System_UIntPtr); public DmdType System_Array => GetWellKnownType(DmdWellKnownType.System_Array); public DmdType System_Collections_IEnumerable => GetWellKnownType(DmdWellKnownType.System_Collections_IEnumerable); public DmdType System_Collections_Generic_IEnumerable_T => GetWellKnownType(DmdWellKnownType.System_Collections_Generic_IEnumerable_T); public DmdType System_Collections_Generic_IList_T => GetWellKnownType(DmdWellKnownType.System_Collections_Generic_IList_T); public DmdType System_Collections_Generic_ICollection_T => GetWellKnownType(DmdWellKnownType.System_Collections_Generic_ICollection_T); public DmdType System_Collections_IEnumerator => GetWellKnownType(DmdWellKnownType.System_Collections_IEnumerator); public DmdType System_Collections_Generic_IEnumerator_T => GetWellKnownType(DmdWellKnownType.System_Collections_Generic_IEnumerator_T); public DmdType System_Collections_Generic_IReadOnlyList_T => GetWellKnownType(DmdWellKnownType.System_Collections_Generic_IReadOnlyList_T); public DmdType System_Collections_Generic_IReadOnlyCollection_T => GetWellKnownType(DmdWellKnownType.System_Collections_Generic_IReadOnlyCollection_T); public DmdType System_Nullable_T => GetWellKnownType(DmdWellKnownType.System_Nullable_T); public DmdType System_DateTime => GetWellKnownType(DmdWellKnownType.System_DateTime); public DmdType System_Runtime_CompilerServices_IsVolatile => GetWellKnownType(DmdWellKnownType.System_Runtime_CompilerServices_IsVolatile); public DmdType System_IDisposable => GetWellKnownType(DmdWellKnownType.System_IDisposable); public DmdType System_TypedReference => GetWellKnownType(DmdWellKnownType.System_TypedReference); public DmdType System_ArgIterator => GetWellKnownType(DmdWellKnownType.System_ArgIterator); public DmdType System_RuntimeArgumentHandle => GetWellKnownType(DmdWellKnownType.System_RuntimeArgumentHandle); public DmdType System_RuntimeFieldHandle => GetWellKnownType(DmdWellKnownType.System_RuntimeFieldHandle); public DmdType System_RuntimeMethodHandle => GetWellKnownType(DmdWellKnownType.System_RuntimeMethodHandle); public DmdType System_RuntimeTypeHandle => GetWellKnownType(DmdWellKnownType.System_RuntimeTypeHandle); public DmdType System_IAsyncResult => GetWellKnownType(DmdWellKnownType.System_IAsyncResult); public DmdType System_AsyncCallback => GetWellKnownType(DmdWellKnownType.System_AsyncCallback); public DmdType System_Type => GetWellKnownType(DmdWellKnownType.System_Type); #pragma warning restore CS1591 // Missing XML comment for publicly visible type or member /// /// Returns a cached type if present else the input type /// /// Type /// Options /// public abstract DmdType Intern(DmdType type, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a pointer type /// /// Element type /// Custom modifiers or null /// Options /// public abstract DmdType MakePointerType(DmdType elementType, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a by-ref type /// /// Element type /// Custom modifiers or null /// Options /// public abstract DmdType MakeByRefType(DmdType elementType, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a SZ array type /// /// Element type /// Custom modifiers or null /// Options /// public abstract DmdType MakeArrayType(DmdType elementType, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a multi-dimensional array type /// /// Element type /// Number of dimensions /// Sizes /// Lower bounds /// Custom modifiers or null /// Options /// public abstract DmdType MakeArrayType(DmdType elementType, int rank, IList sizes, IList lowerBounds, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a generic type /// /// Generic type definition /// Generic arguments /// Custom modifiers or null /// Options /// public abstract DmdType MakeGenericType(DmdType genericTypeDefinition, IList typeArguments, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a generic method /// /// Generic method definition /// Generic arguments /// Options /// public abstract DmdMethodInfo MakeGenericMethod(DmdMethodInfo genericMethodDefinition, IList typeArguments, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a function pointer type /// /// Method signature /// Custom modifiers or null /// Options /// public abstract DmdType MakeFunctionPointerType(DmdMethodSignature methodSignature, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a function pointer type /// /// Flags /// Number of generic parameters /// Return type /// Parameter types /// VarArgs parameter types /// Custom modifiers or null /// Options /// public abstract DmdType MakeFunctionPointerType(DmdSignatureCallingConvention flags, int genericParameterCount, DmdType returnType, IList parameterTypes, IList varArgsParameterTypes, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a generic type parameter /// /// Position /// Declaring type /// public DmdType MakeGenericTypeParameter(int position, DmdType declaringType) => MakeGenericTypeParameter(position, declaringType, string.Empty, 0, null); /// /// Makes a generic type parameter /// /// Position /// Declaring type /// Name /// Attributes /// Custom modifiers or null /// Options /// public abstract DmdType MakeGenericTypeParameter(int position, DmdType declaringType, string name, DmdGenericParameterAttributes attributes, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Makes a generic method parameter /// /// Position /// Declaring method /// public DmdType MakeGenericMethodParameter(int position, DmdMethodBase declaringMethod) => MakeGenericMethodParameter(position, declaringMethod, string.Empty, 0, null); /// /// Makes a generic method parameter /// /// Position /// Declaring method /// Name /// Attributes /// Custom modifiers or null /// Options /// public abstract DmdType MakeGenericMethodParameter(int position, DmdMethodBase declaringMethod, string name, DmdGenericParameterAttributes attributes, IList? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None); /// /// Gets a type /// /// Type /// public DmdType? GetType(Type type) => GetType(type, DmdGetTypeOptions.None); /// /// Gets a type and throws if it couldn't be found /// /// /// public DmdType GetTypeThrow(Type type) => GetType(type, DmdGetTypeOptions.ThrowOnError)!; /// /// Gets a type /// /// Type /// Options /// public DmdType? GetType(Type type, DmdGetTypeOptions options) { if (type is null) throw new ArgumentNullException(nameof(type)); var assemblyQualifiedName = type.AssemblyQualifiedName ?? throw new ArgumentException(); return GetType(assemblyQualifiedName, options); } /// /// Gets a type /// /// Full name of the type () or the assembly qualified name (). /// Version, public key token and culture are optional. /// Options /// public abstract DmdType? GetType(string typeName, DmdGetTypeOptions options); /// /// Gets a type /// /// Full name of the type () or the assembly qualified name (). /// Version, public key token and culture are optional. /// public DmdType? GetType(string typeName) => GetType(typeName, DmdGetTypeOptions.None); /// /// Gets a type and throws if it couldn't be found /// /// Full name of the type () or the assembly qualified name (). /// Version, public key token and culture are optional. /// public DmdType GetTypeThrow(string typeName) => GetType(typeName, DmdGetTypeOptions.ThrowOnError)!; /// /// Creates a new instance of a type /// /// Evaluation context /// Constructor /// Parameters passed to the method /// public abstract object? CreateInstance(object? context, DmdConstructorInfo ctor, object?[] parameters); /// /// Executes a method /// /// Evaluation context /// Method to call /// Instance object or null if it's a static method /// Parameters passed to the method /// public abstract object? Invoke(object? context, DmdMethodBase method, object? obj, object?[]? parameters); /// /// Loads a field /// /// Evaluation context /// Field /// Instance object or null if it's a static field /// public abstract object? LoadField(object? context, DmdFieldInfo field, object? obj); /// /// Stores a value in a field /// /// Evaluation context /// Field /// Instance object or null if it's a static field /// Value to store in the field public abstract void StoreField(object? context, DmdFieldInfo field, object? obj, object? value); } /// /// Options used when creating types /// [Flags] public enum DmdMakeTypeOptions { /// /// No bit is set /// None = 0, /// /// Don't try to resolve a reference /// NoResolve = 0x00000001, } /// /// Options used when finding a type /// [Flags] public enum DmdGetTypeOptions { /// /// No bit is set /// None = 0, /// /// Throw if the type couldn't be found /// ThrowOnError = 0x00000001, /// /// Ignore case /// IgnoreCase = 0x00000002, } /// /// Create-assembly-options /// public enum DmdCreateAssemblyOptions { /// /// No bit is set /// None = 0, /// /// Set if the module is in memory () /// InMemory = 0x00000001, /// /// Set if it's a dynamic module (types can be added at runtime) () /// Dynamic = 0x00000002, /// /// Synthetic assembly, eg. created by the expression compiler /// Synthetic = 0x00000004, /// /// Don't add the assembly to the AppDomain /// DontAddAssembly = 0x00000008, /// /// It's an exe file. If it's not set, it's either a DLL or it's unknown /// IsEXE = 0x00000010, /// /// It's a dll file. If it's not set, it's either an EXE or it's unknown /// IsDLL = 0x00000020, } /// /// Info needed when creating an assembly /// public readonly struct DmdCreateAssemblyInfo { /// /// Gets the options /// public DmdCreateAssemblyOptions Options { get; } /// /// The fully qualified name of the module (). See /// public string FullyQualifiedName { get; } /// /// Location of the assembly or an empty string () /// public string AssemblyLocation { get; } /// /// Gets the assembly's simple name or null if it's unknown /// public string? AssemblySimpleName { get; } /// /// Constructor /// /// Options /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// The assembly's simple name or null if it's unknown public DmdCreateAssemblyInfo(DmdCreateAssemblyOptions options, string fullyQualifiedName, string assemblyLocation, string? assemblySimpleName) { if ((options & (DmdCreateAssemblyOptions.IsEXE | DmdCreateAssemblyOptions.IsDLL)) == (DmdCreateAssemblyOptions.IsEXE | DmdCreateAssemblyOptions.IsDLL)) throw new ArgumentException(); Options = options; FullyQualifiedName = fullyQualifiedName ?? throw new ArgumentNullException(nameof(fullyQualifiedName)); AssemblyLocation = assemblyLocation ?? throw new ArgumentNullException(nameof(assemblyLocation)); AssemblySimpleName = assemblySimpleName; } /// /// Constructor /// /// true if the module is in memory () /// true if it's a dynamic module (types can be added at runtime) () /// true if it's a synthetic assembly, eg. created by the expression compiler /// true if the assembly should be added to the AppDomain /// The fully qualified name of the module (). See /// Location of the assembly or an empty string () /// The assembly's simple name or null if it's unknown public DmdCreateAssemblyInfo(bool isInMemory, bool isDynamic, bool isSynthetic, bool addAssembly, string fullyQualifiedName, string assemblyLocation, string? assemblySimpleName) : this(GetOptions(isInMemory, isDynamic, isSynthetic, addAssembly), fullyQualifiedName, assemblyLocation, assemblySimpleName) { } static DmdCreateAssemblyOptions GetOptions(bool isInMemory, bool isDynamic, bool isSynthetic, bool addAssembly) { var options = DmdCreateAssemblyOptions.None; if (isInMemory) options |= DmdCreateAssemblyOptions.InMemory; if (isDynamic) options |= DmdCreateAssemblyOptions.Dynamic; if (isSynthetic) options |= DmdCreateAssemblyOptions.Synthetic; if (!addAssembly) options |= DmdCreateAssemblyOptions.DontAddAssembly; return options; } } }