772 lines
41 KiB
C#
Raw Normal View History

2021-09-20 18:20:01 +02:00
/*
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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
namespace dnSpy.Debugger.DotNet.Metadata {
/// <summary>
/// A .NET AppDomain
/// </summary>
public abstract class DmdAppDomain : DmdObject {
/// <summary>
/// Dummy abstract method to make sure no-one outside this assembly can create their own <see cref="DmdAppDomain"/>
/// </summary>
private protected abstract void YouCantDeriveFromThisClass();
/// <summary>
/// Gets the runtime
/// </summary>
public abstract DmdRuntime Runtime { get; }
/// <summary>
/// Gets the unique AppDomain id
/// </summary>
public abstract int Id { get; }
/// <summary>
/// Creates an assembly and adds it to the AppDomain. The first created assembly must be the corlib (<see cref="DmdAppDomain.CorLib"/>)
/// </summary>
/// <param name="getMetadata">Called to provide the metadata</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <returns></returns>
public DmdAssembly CreateAssembly(Func<DmdLazyMetadataBytes> getMetadata, bool isInMemory, bool isDynamic, string fullyQualifiedName, string assemblyLocation) =>
CreateAssembly(getMetadata, isInMemory, isDynamic, fullyQualifiedName, assemblyLocation, assemblySimpleName: null, isSynthetic: false, addAssembly: true);
/// <summary>
/// Creates a synthetic assembly but does not add it to the AppDomain
/// </summary>
/// <param name="getMetadata">Called to provide the metadata</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <param name="assemblySimpleName">The assembly's simple name or null if it's unknown</param>
/// <returns></returns>
public DmdAssembly CreateSyntheticAssembly(Func<DmdLazyMetadataBytes> getMetadata, bool isInMemory, bool isDynamic, string fullyQualifiedName, string assemblyLocation, string? assemblySimpleName) =>
CreateAssembly(getMetadata, isInMemory, isDynamic, fullyQualifiedName, assemblyLocation, assemblySimpleName: assemblySimpleName, isSynthetic: true, addAssembly: false);
/// <summary>
/// Creates an assembly and optionally adds it to the AppDomain. The first created assembly must be the corlib (<see cref="DmdAppDomain.CorLib"/>)
/// </summary>
/// <param name="getMetadata">Called to provide the metadata</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <param name="assemblySimpleName">The assembly's simple name or null if it's unknown</param>
/// <param name="isSynthetic">true if it's a synthetic assembly; it's not loaded in the debugged process</param>
/// <param name="addAssembly">true if the assembly should be added to the AppDomain</param>
/// <returns></returns>
public DmdAssembly CreateAssembly(Func<DmdLazyMetadataBytes> 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));
/// <summary>
/// Creates an assembly and optionally adds it to the AppDomain. The first created assembly must be the corlib (<see cref="DmdAppDomain.CorLib"/>)
/// </summary>
/// <param name="getMetadata">Called to provide the metadata</param>
/// <param name="assemblyInfo">Assembly info</param>
/// <returns></returns>
public abstract DmdAssembly CreateAssembly(Func<DmdLazyMetadataBytes> getMetadata, DmdCreateAssemblyInfo assemblyInfo);
/// <summary>
/// Creates an assembly. The first created assembly must be the corlib (<see cref="DmdAppDomain.CorLib"/>)
/// </summary>
/// <param name="filename">Filename</param>
/// <param name="isFileLayout">true if file layout, false if memory layout</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <returns></returns>
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);
}
/// <summary>
/// Creates an assembly. The first created assembly must be the corlib (<see cref="DmdAppDomain.CorLib"/>)
/// </summary>
/// <param name="address">Address of PE file</param>
/// <param name="size">Size of PE file</param>
/// <param name="isFileLayout">true if file layout, false if memory layout</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <returns></returns>
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);
/// <summary>
/// Creates an assembly. The first created assembly must be the corlib (<see cref="DmdAppDomain.CorLib"/>)
/// </summary>
/// <param name="assemblyBytes">Raw PE file bytes</param>
/// <param name="isFileLayout">true if file layout, false if memory layout</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <returns></returns>
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);
}
/// <summary>
/// Creates an assembly. The first created assembly must be the corlib (<see cref="DmdAppDomain.CorLib"/>)
/// </summary>
/// <param name="comMetadata">COM <c>IMetaDataImport</c> instance</param>
/// <param name="dynamicModuleHelper">Helper class</param>
/// <param name="dispatcher">Dispatcher to use when accessing <paramref name="comMetadata"/></param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <returns></returns>
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);
}
/// <summary>
/// Adds a module to an existing assembly
/// </summary>
/// <param name="assembly">Assembly</param>
/// <param name="getMetadata">Called to provide the metadata</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <returns></returns>
public abstract DmdModule CreateModule(DmdAssembly assembly, Func<DmdLazyMetadataBytes> getMetadata, bool isInMemory, bool isDynamic, string fullyQualifiedName);
/// <summary>
/// Adds a module to an existing assembly
/// </summary>
/// <param name="assembly">Assembly</param>
/// <param name="filename">Filename</param>
/// <param name="isFileLayout">true if file layout, false if memory layout</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <returns></returns>
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);
}
/// <summary>
/// Adds a module to an existing assembly
/// </summary>
/// <param name="assembly">Assembly</param>
/// <param name="address">Address of the PE file</param>
/// <param name="size">Size of the PE file</param>
/// <param name="isFileLayout">true if file layout, false if memory layout</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <returns></returns>
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);
/// <summary>
/// Adds a module to an existing assembly
/// </summary>
/// <param name="assembly">Assembly</param>
/// <param name="moduleBytes">Raw PE file bytes</param>
/// <param name="isFileLayout">true if file layout, false if memory layout</param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <returns></returns>
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);
}
/// <summary>
/// Adds a module to an existing assembly
/// </summary>
/// <param name="assembly">Assembly</param>
/// <param name="comMetadata">COM <c>IMetaDataImport</c> instance</param>
/// <param name="dynamicModuleHelper">Helper class</param>
/// <param name="dispatcher">Dispatcher to use when accessing <paramref name="comMetadata"/></param>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <returns></returns>
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);
}
/// <summary>
/// Adds an assembly
/// </summary>
/// <param name="assembly">Assembly to add</param>
public abstract void Add(DmdAssembly assembly);
/// <summary>
/// Removes an assembly
/// </summary>
/// <param name="assembly">Assembly to remove</param>
public abstract void Remove(DmdAssembly assembly);
/// <summary>
/// Adds an assembly. It gets removed when the return value's <see cref="IDisposable.Dispose"/> method gets called
/// </summary>
/// <param name="assembly">Assembly to add</param>
/// <returns></returns>
public TemporaryAssemblyDisposable AddTemporaryAssembly(DmdAssembly assembly) => new TemporaryAssemblyDisposable(assembly);
/// <summary>
/// Adds and removes an assembly
/// </summary>
public readonly struct TemporaryAssemblyDisposable : IDisposable {
readonly DmdAssembly assembly;
internal TemporaryAssemblyDisposable(DmdAssembly assembly) {
this.assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
assembly.AppDomain.Add(assembly);
}
/// <summary>
/// Dispose()
/// </summary>
public void Dispose() => assembly.AppDomain.Remove(assembly);
}
/// <summary>
/// Gets all assemblies
/// </summary>
/// <returns></returns>
public DmdAssembly[] GetAssemblies() => GetAssemblies(includeSyntheticAssemblies: true);
/// <summary>
/// Gets all assemblies
/// </summary>
/// <param name="includeSyntheticAssemblies">true to include synthetic assemblies</param>
/// <returns></returns>
public abstract DmdAssembly[] GetAssemblies(bool includeSyntheticAssemblies);
/// <summary>
/// Gets an assembly or returns null if there's no such assembly
/// </summary>
/// <param name="simpleName">Simple name of the assembly, eg. "System"</param>
/// <returns></returns>
public abstract DmdAssembly? GetAssembly(string simpleName);
/// <summary>
/// Gets an assembly or returns null if there's no such assembly
/// </summary>
/// <param name="name">Assembly name</param>
/// <returns></returns>
public abstract DmdAssembly? GetAssembly(IDmdAssemblyName name);
/// <summary>
/// Loads an assembly
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="assemblyName">Full assembly name</param>
/// <returns></returns>
public DmdAssembly? Load(object? context, string assemblyName) => Load(context, new DmdReadOnlyAssemblyName(assemblyName));
/// <summary>
/// Loads an assembly
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="name">Assembly name</param>
/// <returns></returns>
public abstract DmdAssembly? Load(object? context, IDmdAssemblyName name);
/// <summary>
/// Loads an assembly. Will fail on .NET Core 1.x (but not on .NET Core 2.x or later)
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="assemblyFile">Assembly name or path to assembly</param>
/// <returns></returns>
public abstract DmdAssembly? LoadFrom(object? context, string assemblyFile);
/// <summary>
/// Loads an assembly. Will fail on .NET Core 1.x (but not on .NET Core 2.x or later)
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="path">Path to assembly</param>
/// <returns></returns>
public abstract DmdAssembly? LoadFile(object? context, string path);
/// <summary>
/// Gets the core library (eg. mscorlib if it's .NET Framework)
/// </summary>
public abstract DmdAssembly? CorLib { get; }
/// <summary>
/// Checks if a well known type exists in one of the loaded assemblies
/// </summary>
/// <param name="wellKnownType">Well known type</param>
/// <returns></returns>
public bool HasWellKnownType(DmdWellKnownType wellKnownType) => GetWellKnownType(wellKnownType, isOptional: true) is not null;
/// <summary>
/// Gets a well known type
/// </summary>
/// <param name="wellKnownType">Well known type</param>
/// <returns></returns>
public DmdType GetWellKnownType(DmdWellKnownType wellKnownType) => GetWellKnownType(wellKnownType, isOptional: false)!;
/// <summary>
/// Gets a well known type
/// </summary>
/// <param name="wellKnownType">Well known type</param>
/// <param name="isOptional">Used if the type couldn't be found. If true, null is returned, and if false, an exception is thrown</param>
/// <returns></returns>
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
/// <summary>
/// Returns a cached type if present else the input type
/// </summary>
/// <param name="type">Type</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType Intern(DmdType type, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a pointer type
/// </summary>
/// <param name="elementType">Element type</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakePointerType(DmdType elementType, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a by-ref type
/// </summary>
/// <param name="elementType">Element type</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeByRefType(DmdType elementType, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a SZ array type
/// </summary>
/// <param name="elementType">Element type</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeArrayType(DmdType elementType, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a multi-dimensional array type
/// </summary>
/// <param name="elementType">Element type</param>
/// <param name="rank">Number of dimensions</param>
/// <param name="sizes">Sizes</param>
/// <param name="lowerBounds">Lower bounds</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeArrayType(DmdType elementType, int rank, IList<int> sizes, IList<int> lowerBounds, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a generic type
/// </summary>
/// <param name="genericTypeDefinition">Generic type definition</param>
/// <param name="typeArguments">Generic arguments</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeGenericType(DmdType genericTypeDefinition, IList<DmdType> typeArguments, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a generic method
/// </summary>
/// <param name="genericMethodDefinition">Generic method definition</param>
/// <param name="typeArguments">Generic arguments</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdMethodInfo MakeGenericMethod(DmdMethodInfo genericMethodDefinition, IList<DmdType> typeArguments, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a function pointer type
/// </summary>
/// <param name="methodSignature">Method signature</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeFunctionPointerType(DmdMethodSignature methodSignature, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a function pointer type
/// </summary>
/// <param name="flags">Flags</param>
/// <param name="genericParameterCount">Number of generic parameters</param>
/// <param name="returnType">Return type</param>
/// <param name="parameterTypes">Parameter types</param>
/// <param name="varArgsParameterTypes">VarArgs parameter types</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeFunctionPointerType(DmdSignatureCallingConvention flags, int genericParameterCount, DmdType returnType, IList<DmdType> parameterTypes, IList<DmdType> varArgsParameterTypes, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a generic type parameter
/// </summary>
/// <param name="position">Position</param>
/// <param name="declaringType">Declaring type</param>
/// <returns></returns>
public DmdType MakeGenericTypeParameter(int position, DmdType declaringType) => MakeGenericTypeParameter(position, declaringType, string.Empty, 0, null);
/// <summary>
/// Makes a generic type parameter
/// </summary>
/// <param name="position">Position</param>
/// <param name="declaringType">Declaring type</param>
/// <param name="name">Name</param>
/// <param name="attributes">Attributes</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeGenericTypeParameter(int position, DmdType declaringType, string name, DmdGenericParameterAttributes attributes, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Makes a generic method parameter
/// </summary>
/// <param name="position">Position</param>
/// <param name="declaringMethod">Declaring method</param>
/// <returns></returns>
public DmdType MakeGenericMethodParameter(int position, DmdMethodBase declaringMethod) => MakeGenericMethodParameter(position, declaringMethod, string.Empty, 0, null);
/// <summary>
/// Makes a generic method parameter
/// </summary>
/// <param name="position">Position</param>
/// <param name="declaringMethod">Declaring method</param>
/// <param name="name">Name</param>
/// <param name="attributes">Attributes</param>
/// <param name="customModifiers">Custom modifiers or null</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType MakeGenericMethodParameter(int position, DmdMethodBase declaringMethod, string name, DmdGenericParameterAttributes attributes, IList<DmdCustomModifier>? customModifiers, DmdMakeTypeOptions options = DmdMakeTypeOptions.None);
/// <summary>
/// Gets a type
/// </summary>
/// <param name="type">Type</param>
/// <returns></returns>
public DmdType? GetType(Type type) => GetType(type, DmdGetTypeOptions.None);
/// <summary>
/// Gets a type and throws if it couldn't be found
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public DmdType GetTypeThrow(Type type) => GetType(type, DmdGetTypeOptions.ThrowOnError)!;
/// <summary>
/// Gets a type
/// </summary>
/// <param name="type">Type</param>
/// <param name="options">Options</param>
/// <returns></returns>
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);
}
/// <summary>
/// Gets a type
/// </summary>
/// <param name="typeName">Full name of the type (<see cref="DmdType.FullName"/>) or the assembly qualified name (<see cref="DmdType.AssemblyQualifiedName"/>).
/// Version, public key token and culture are optional.</param>
/// <param name="options">Options</param>
/// <returns></returns>
public abstract DmdType? GetType(string typeName, DmdGetTypeOptions options);
/// <summary>
/// Gets a type
/// </summary>
/// <param name="typeName">Full name of the type (<see cref="DmdType.FullName"/>) or the assembly qualified name (<see cref="DmdType.AssemblyQualifiedName"/>).
/// Version, public key token and culture are optional.</param>
/// <returns></returns>
public DmdType? GetType(string typeName) => GetType(typeName, DmdGetTypeOptions.None);
/// <summary>
/// Gets a type and throws if it couldn't be found
/// </summary>
/// <param name="typeName">Full name of the type (<see cref="DmdType.FullName"/>) or the assembly qualified name (<see cref="DmdType.AssemblyQualifiedName"/>).
/// Version, public key token and culture are optional.</param>
/// <returns></returns>
public DmdType GetTypeThrow(string typeName) => GetType(typeName, DmdGetTypeOptions.ThrowOnError)!;
/// <summary>
/// Creates a new instance of a type
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="ctor">Constructor</param>
/// <param name="parameters">Parameters passed to the method</param>
/// <returns></returns>
public abstract object? CreateInstance(object? context, DmdConstructorInfo ctor, object?[] parameters);
/// <summary>
/// Executes a method
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="method">Method to call</param>
/// <param name="obj">Instance object or null if it's a static method</param>
/// <param name="parameters">Parameters passed to the method</param>
/// <returns></returns>
public abstract object? Invoke(object? context, DmdMethodBase method, object? obj, object?[]? parameters);
/// <summary>
/// Loads a field
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="field">Field</param>
/// <param name="obj">Instance object or null if it's a static field</param>
/// <returns></returns>
public abstract object? LoadField(object? context, DmdFieldInfo field, object? obj);
/// <summary>
/// Stores a value in a field
/// </summary>
/// <param name="context">Evaluation context</param>
/// <param name="field">Field</param>
/// <param name="obj">Instance object or null if it's a static field</param>
/// <param name="value">Value to store in the field</param>
public abstract void StoreField(object? context, DmdFieldInfo field, object? obj, object? value);
}
/// <summary>
/// Options used when creating types
/// </summary>
[Flags]
public enum DmdMakeTypeOptions {
/// <summary>
/// No bit is set
/// </summary>
None = 0,
/// <summary>
/// Don't try to resolve a reference
/// </summary>
NoResolve = 0x00000001,
}
/// <summary>
/// Options used when finding a type
/// </summary>
[Flags]
public enum DmdGetTypeOptions {
/// <summary>
/// No bit is set
/// </summary>
None = 0,
/// <summary>
/// Throw if the type couldn't be found
/// </summary>
ThrowOnError = 0x00000001,
/// <summary>
/// Ignore case
/// </summary>
IgnoreCase = 0x00000002,
}
/// <summary>
/// Create-assembly-options
/// </summary>
public enum DmdCreateAssemblyOptions {
/// <summary>
/// No bit is set
/// </summary>
None = 0,
/// <summary>
/// Set if the module is in memory (<see cref="DmdModule.IsInMemory"/>)
/// </summary>
InMemory = 0x00000001,
/// <summary>
/// Set if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)
/// </summary>
Dynamic = 0x00000002,
/// <summary>
/// Synthetic assembly, eg. created by the expression compiler
/// </summary>
Synthetic = 0x00000004,
/// <summary>
/// Don't add the assembly to the AppDomain
/// </summary>
DontAddAssembly = 0x00000008,
/// <summary>
/// It's an exe file. If it's not set, it's either a DLL or it's unknown
/// </summary>
IsEXE = 0x00000010,
/// <summary>
/// It's a dll file. If it's not set, it's either an EXE or it's unknown
/// </summary>
IsDLL = 0x00000020,
}
/// <summary>
/// Info needed when creating an assembly
/// </summary>
public readonly struct DmdCreateAssemblyInfo {
/// <summary>
/// Gets the options
/// </summary>
public DmdCreateAssemblyOptions Options { get; }
/// <summary>
/// The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/>
/// </summary>
public string FullyQualifiedName { get; }
/// <summary>
/// Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)
/// </summary>
public string AssemblyLocation { get; }
/// <summary>
/// Gets the assembly's simple name or null if it's unknown
/// </summary>
public string? AssemblySimpleName { get; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="options">Options</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <param name="assemblySimpleName">The assembly's simple name or null if it's unknown</param>
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;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="isInMemory">true if the module is in memory (<see cref="DmdModule.IsInMemory"/>)</param>
/// <param name="isDynamic">true if it's a dynamic module (types can be added at runtime) (<see cref="DmdModule.IsDynamic"/>)</param>
/// <param name="isSynthetic">true if it's a synthetic assembly, eg. created by the expression compiler</param>
/// <param name="addAssembly">true if the assembly should be added to the AppDomain</param>
/// <param name="fullyQualifiedName">The fully qualified name of the module (<see cref="DmdModule.FullyQualifiedName"/>). See <see cref="DmdModule.GetFullyQualifiedName(bool, bool, string)"/></param>
/// <param name="assemblyLocation">Location of the assembly or an empty string (<see cref="DmdAssembly.Location"/>)</param>
/// <param name="assemblySimpleName">The assembly's simple name or null if it's unknown</param>
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;
}
}
}