/*
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;
using System.Collections.ObjectModel;
using dnSpy.Debugger.DotNet.Metadata.Impl;
namespace dnSpy.Debugger.DotNet.Metadata {
///
/// A .NET assembly
///
public abstract class DmdAssembly : DmdObject, IDmdCustomAttributeProvider, IDmdSecurityAttributeProvider {
///
/// Dummy abstract method to make sure no-one outside this assembly can create their own
///
private protected abstract void YouCantDeriveFromThisClass();
///
/// Gets the AppDomain
///
public abstract DmdAppDomain AppDomain { get; }
///
/// true if this is the corlib assembly
///
public bool IsCorLib => this == AppDomain.CorLib;
///
/// Creates a qualified type name
///
/// Full assembly name of the type
/// Full type name
///
public static string CreateQualifiedName(string assemblyName, string typeName) => typeName + ", " + assemblyName;
///
/// Gets the assembly name
///
///
public abstract DmdReadOnlyAssemblyName GetName();
///
/// Gets the full name of the assembly
///
public string FullName => GetName().ToString();
///
/// Gets the assembly location or an empty string
///
public abstract string Location { get; }
///
/// Gets the runtime version found in the metadata
///
public abstract string ImageRuntimeVersion { get; }
///
/// true if it's a dynamic assembly (types can be added at runtime)
///
public bool IsDynamic => ManifestModule.IsDynamic;
///
/// true if it's an in-memory assembly (eg. loaded from a array)
///
public bool IsInMemory => ManifestModule.IsInMemory;
///
/// true if it's a synthetic assembly; it's not loaded in the debugged process
///
public bool IsSynthetic => ManifestModule.IsSynthetic;
///
/// true if the assembly has been added to its AppDomain
///
public abstract bool IsLoaded { get; }
///
/// Gets the entry point or null
///
public abstract DmdMethodInfo? EntryPoint { get; }
///
/// Gets the first module of this assembly
///
public abstract DmdModule ManifestModule { get; }
///
/// 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 fullname = type.FullName ?? throw new ArgumentException();
return GetType(fullname, options);
}
///
/// Gets a type in this assembly or null if it doesn't exist
///
/// Name of type
///
public DmdType? GetType(string name) => GetType(name, DmdGetTypeOptions.None);
///
/// Gets a type and throws if it couldn't be found
///
/// Name of type
///
public DmdType GetTypeThrow(string name) => GetType(name, DmdGetTypeOptions.ThrowOnError)!;
///
/// Gets a type in this assembly
///
/// Name of type
/// true to throw if the type doesn't exist
///
public DmdType? GetType(string name, bool throwOnError) => GetType(name, throwOnError ? DmdGetTypeOptions.ThrowOnError : DmdGetTypeOptions.None);
///
/// Gets a type in this assembly
///
/// Name of type
/// true to throw if the type doesn't exist
/// true if case insensitive comparisons
///
public DmdType? GetType(string name, bool throwOnError, bool ignoreCase) =>
GetType(name, (throwOnError ? DmdGetTypeOptions.ThrowOnError : 0) | (ignoreCase ? DmdGetTypeOptions.IgnoreCase : 0));
///
/// Gets a type
///
/// Full name of the type ()
/// Options
///
public abstract DmdType? GetType(string typeName, DmdGetTypeOptions options);
///
/// Gets all public types in this assembly
///
public IEnumerable ExportedTypes => GetExportedTypes();
///
/// Gets all public types in this assembly
///
public abstract DmdType[] GetExportedTypes();
///
/// Gets all forwarded types (types that now exist in another assembly)
///
///
public abstract DmdType[] GetForwardedTypes();
///
/// Gets all types in this assembly
///
///
public DmdType[] GetTypes() {
var modules = GetModules();
if (modules.Length == 1)
return modules[0].GetTypes();
var list = new List();
foreach (var module in modules)
list.AddRange(module.GetTypes());
return list.ToArray();
}
///
/// Gets the security attributes
///
public ReadOnlyCollection SecurityAttributes => GetSecurityAttributesData();
///
/// Gets the security attributes
///
///
public abstract ReadOnlyCollection GetSecurityAttributesData();
///
/// Gets the custom attributes
///
public ReadOnlyCollection CustomAttributes => GetCustomAttributesData();
///
/// Gets the custom attributes
///
///
public abstract ReadOnlyCollection GetCustomAttributesData();
///
/// Checks if a custom attribute is present
///
/// Full name of the custom attribute type
/// true to check custom attributes in all base classes
///
public bool IsDefined(string attributeTypeFullName, bool inherit) => CustomAttributesHelper.IsDefined(GetCustomAttributesData(), attributeTypeFullName);
///
/// Checks if a custom attribute is present
///
/// Custom attribute type
/// true to check custom attributes in all base classes
///
public bool IsDefined(DmdType? attributeType, bool inherit) => CustomAttributesHelper.IsDefined(GetCustomAttributesData(), attributeType);
///
/// Checks if a custom attribute is present
///
/// Custom attribute type
/// true to check custom attributes in all base classes
///
public bool IsDefined(Type attributeType, bool inherit) => CustomAttributesHelper.IsDefined(GetCustomAttributesData(), DmdTypeUtilities.ToDmdType(attributeType, AppDomain));
///
/// Finds a custom attribute
///
/// Full name of the custom attribute type
/// true to check custom attributes in all base classes
///
public DmdCustomAttributeData? FindCustomAttribute(string attributeTypeFullName, bool inherit) => CustomAttributesHelper.Find(GetCustomAttributesData(), attributeTypeFullName);
///
/// Finds a custom attribute
///
/// Custom attribute type
/// true to check custom attributes in all base classes
///
public DmdCustomAttributeData? FindCustomAttribute(DmdType? attributeType, bool inherit) => CustomAttributesHelper.Find(GetCustomAttributesData(), attributeType);
///
/// Finds a custom attribute
///
/// Custom attribute type
/// true to check custom attributes in all base classes
///
public DmdCustomAttributeData? FindCustomAttribute(Type attributeType, bool inherit) => CustomAttributesHelper.Find(GetCustomAttributesData(), DmdTypeUtilities.ToDmdType(attributeType, AppDomain));
///
/// Creates an instance of a type
///
/// Evaluation context
/// Fully qualified name of type to create
public object? CreateInstance(object? context, string typeName) => CreateInstance(context, typeName, false, DmdBindingFlags.Instance | DmdBindingFlags.Public, null, (IList?)null);
///
/// Creates an instance of a type
///
/// Evaluation context
/// Fully qualified name of type to create
/// true to ignore case
public object? CreateInstance(object? context, string typeName, bool ignoreCase) => CreateInstance(context, typeName, ignoreCase, DmdBindingFlags.Instance | DmdBindingFlags.Public, null, (IList?)null);
///
/// Creates an instance of a type
///
/// Evaluation context
/// Fully qualified name of type to create
/// true to ignore case
/// Binding attributes
/// Constructor arguments or null
public object? CreateInstance(object? context, string typeName, bool ignoreCase, DmdBindingFlags bindingAttr, object?[]? args) => CreateInstance(context, typeName, ignoreCase, bindingAttr, args, (IList?)null);
///
/// Creates an instance of a type
///
/// Evaluation context
/// Fully qualified name of type to create
/// true to ignore case
/// Binding attributes
/// Constructor arguments or null
/// Constructor parameter types or null
///
public object? CreateInstance(object? context, string typeName, bool ignoreCase, DmdBindingFlags bindingAttr, object?[]? args, IList? argTypes) {
args ??= Array.Empty