// dnlib: See LICENSE.txt for more info
using System;
using System.Threading;
using dnlib.Utils;
using dnlib.PE;
using dnlib.DotNet.MD;
using dnlib.DotNet.Emit;
using dnlib.Threading;
using dnlib.DotNet.Pdb;
using System.Collections.Generic;
using System.Diagnostics;
namespace dnlib.DotNet {
///
/// A high-level representation of a row in the Method table
///
public abstract class MethodDef : IHasCustomAttribute, IHasDeclSecurity, IMemberRefParent, IMethodDefOrRef, IMemberForwarded, ICustomAttributeType, ITypeOrMethodDef, IManagedEntryPoint, IHasCustomDebugInformation, IListListener, IListListener, IMemberDef {
internal static readonly UTF8String StaticConstructorName = ".cctor";
internal static readonly UTF8String InstanceConstructorName = ".ctor";
///
/// The row id in its table
///
protected uint rid;
#if THREAD_SAFE
readonly Lock theLock = Lock.Create();
#endif
///
/// All parameters
///
protected ParameterList parameterList;
///
public MDToken MDToken => new MDToken(Table.Method, rid);
///
public uint Rid {
get => rid;
set => rid = value;
}
///
public int HasCustomAttributeTag => 0;
///
public int HasDeclSecurityTag => 1;
///
public int MemberRefParentTag => 3;
///
public int MethodDefOrRefTag => 0;
///
public int MemberForwardedTag => 1;
///
public int CustomAttributeTypeTag => 2;
///
public int TypeOrMethodDefTag => 1;
///
/// From column Method.RVA
///
public RVA RVA {
get => rva;
set => rva = value;
}
///
protected RVA rva;
///
/// From column Method.ImplFlags
///
public MethodImplAttributes ImplAttributes {
get => (MethodImplAttributes)implAttributes;
set => implAttributes = (int)value;
}
/// Implementation attributes
protected int implAttributes;
///
/// From column Method.Flags
///
public MethodAttributes Attributes {
get => (MethodAttributes)attributes;
set => attributes = (int)value;
}
/// Attributes
protected int attributes;
///
/// From column Method.Name
///
public UTF8String Name {
get => name;
set => name = value;
}
/// Name
protected UTF8String name;
///
/// From column Method.Signature
///
public CallingConventionSig Signature {
get => signature;
set => signature = value;
}
///
protected CallingConventionSig signature;
///
/// From column Method.ParamList
///
public IList ParamDefs {
get {
if (paramDefs is null)
InitializeParamDefs();
return paramDefs;
}
}
///
protected LazyList paramDefs;
/// Initializes
protected virtual void InitializeParamDefs() =>
Interlocked.CompareExchange(ref paramDefs, new LazyList(this), null);
///
public IList GenericParameters {
get {
if (genericParameters is null)
InitializeGenericParameters();
return genericParameters;
}
}
///
protected LazyList genericParameters;
/// Initializes
protected virtual void InitializeGenericParameters() =>
Interlocked.CompareExchange(ref genericParameters, new LazyList(this), null);
///
public IList DeclSecurities {
get {
if (declSecurities is null)
InitializeDeclSecurities();
return declSecurities;
}
}
///
protected IList declSecurities;
/// Initializes
protected virtual void InitializeDeclSecurities() =>
Interlocked.CompareExchange(ref declSecurities, new List(), null);
///
public ImplMap ImplMap {
get {
if (!implMap_isInitialized)
InitializeImplMap();
return implMap;
}
set {
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
implMap = value;
implMap_isInitialized = true;
#if THREAD_SAFE
} finally { theLock.ExitWriteLock(); }
#endif
}
}
///
protected ImplMap implMap;
///
protected bool implMap_isInitialized;
void InitializeImplMap() {
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
if (implMap_isInitialized)
return;
implMap = GetImplMap_NoLock();
implMap_isInitialized = true;
#if THREAD_SAFE
} finally { theLock.ExitWriteLock(); }
#endif
}
/// Called to initialize
protected virtual ImplMap GetImplMap_NoLock() => null;
/// Reset
protected void ResetImplMap() => implMap_isInitialized = false;
///
/// Gets/sets the method body. See also
///
public MethodBody MethodBody {
get {
if (!methodBody_isInitialized)
InitializeMethodBody();
return methodBody;
}
set {
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
methodBody = value;
methodBody_isInitialized = true;
#if THREAD_SAFE
} finally { theLock.ExitWriteLock(); }
#endif
}
}
///
protected MethodBody methodBody;
///
protected bool methodBody_isInitialized;
void InitializeMethodBody() {
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
if (methodBody_isInitialized)
return;
methodBody = GetMethodBody_NoLock();
methodBody_isInitialized = true;
#if THREAD_SAFE
} finally { theLock.ExitWriteLock(); }
#endif
}
///
/// Frees the method body if it has been loaded. This does nothing if
/// returns false.
///
public void FreeMethodBody() {
if (!CanFreeMethodBody)
return;
if (!methodBody_isInitialized)
return;
#if THREAD_SAFE
theLock.EnterWriteLock(); try {
#endif
methodBody = null;
methodBody_isInitialized = false;
#if THREAD_SAFE
} finally { theLock.ExitWriteLock(); }
#endif
}
/// Called to initialize
protected virtual MethodBody GetMethodBody_NoLock() => null;
///
/// true if can free the method body
///
protected virtual bool CanFreeMethodBody => true;
///
/// Gets all custom attributes
///
public CustomAttributeCollection CustomAttributes {
get {
if (customAttributes is null)
InitializeCustomAttributes();
return customAttributes;
}
}
///
protected CustomAttributeCollection customAttributes;
/// Initializes
protected virtual void InitializeCustomAttributes() =>
Interlocked.CompareExchange(ref customAttributes, new CustomAttributeCollection(), null);
///
public int HasCustomDebugInformationTag => 0;
///
public bool HasCustomDebugInfos => CustomDebugInfos.Count > 0;
///
/// Gets all custom debug infos
///
public IList CustomDebugInfos {
get {
if (customDebugInfos is null)
InitializeCustomDebugInfos();
return customDebugInfos;
}
}
///
protected IList customDebugInfos;
/// Initializes
protected virtual void InitializeCustomDebugInfos() =>
Interlocked.CompareExchange(ref customDebugInfos, new List(), null);
///
/// Gets the methods this method implements
///
public IList Overrides {
get {
if (overrides is null)
InitializeOverrides();
return overrides;
}
}
///
protected IList overrides;
/// Initializes
protected virtual void InitializeOverrides() =>
Interlocked.CompareExchange(ref overrides, new List(), null);
///
/// Gets the export info or null if the method isn't exported to unmanaged code.
///
public MethodExportInfo ExportInfo {
get => exportInfo;
set => exportInfo = value;
}
///
protected MethodExportInfo exportInfo;
///
public bool HasCustomAttributes => CustomAttributes.Count > 0;
///
public bool HasDeclSecurities => DeclSecurities.Count > 0;
///
/// true if is not empty
///
public bool HasParamDefs => ParamDefs.Count > 0;
///
/// Gets/sets the declaring type (owner type)
///
public TypeDef DeclaringType {
get => declaringType2;
set {
var currentDeclaringType = DeclaringType2;
if (currentDeclaringType == value)
return;
if (currentDeclaringType is not null)
currentDeclaringType.Methods.Remove(this); // Will set DeclaringType2 = null
if (value is not null)
value.Methods.Add(this); // Will set DeclaringType2 = value
}
}
///
ITypeDefOrRef IMemberRef.DeclaringType => declaringType2;
///
/// Called by and should normally not be called by any user
/// code. Use instead. Only call this if you must set the
/// declaring type without inserting it in the declaring type's method list.
///
public TypeDef DeclaringType2 {
get => declaringType2;
set => declaringType2 = value;
}
///
protected TypeDef declaringType2;
///
public ModuleDef Module => declaringType2?.Module;
bool IIsTypeOrMethod.IsType => false;
bool IIsTypeOrMethod.IsMethod => true;
bool IMemberRef.IsField => false;
bool IMemberRef.IsTypeSpec => false;
bool IMemberRef.IsTypeRef => false;
bool IMemberRef.IsTypeDef => false;
bool IMemberRef.IsMethodSpec => false;
bool IMemberRef.IsMethodDef => true;
bool IMemberRef.IsMemberRef => false;
bool IMemberRef.IsFieldDef => false;
bool IMemberRef.IsPropertyDef => false;
bool IMemberRef.IsEventDef => false;
bool IMemberRef.IsGenericParam => false;
///
/// Gets/sets the CIL method body. See also
///
public CilBody Body {
get {
if (!methodBody_isInitialized)
InitializeMethodBody();
return methodBody as CilBody;
}
set => MethodBody = value;
}
///
/// Gets/sets the native method body
///
public NativeMethodBody NativeBody {
get {
if (!methodBody_isInitialized)
InitializeMethodBody();
return methodBody as NativeMethodBody;
}
set => MethodBody = value;
}
///
/// true if there's at least one in
///
public bool HasGenericParameters => GenericParameters.Count > 0;
///
/// true if it has a
///
public bool HasBody => Body is not null;
///
/// true if there's at least one in
///
public bool HasOverrides => Overrides.Count > 0;
///
/// true if is not null
///
public bool HasImplMap => ImplMap is not null;
///
/// Gets the full name
///
public string FullName => FullNameFactory.MethodFullName(declaringType2?.FullName, name, MethodSig, null, null, this, null);
///
/// Gets/sets the
///
public MethodSig MethodSig {
get => signature as MethodSig;
set => signature = value;
}
///
/// Gets the parameters
///
public ParameterList Parameters => parameterList;
///
int IGenericParameterProvider.NumberOfGenericParameters {
get {
var sig = MethodSig;
return sig is null ? 0 : (int)sig.GenParamCount;
}
}
///
/// true if the method has a hidden 'this' parameter
///
public bool HasThis {
get {
var ms = MethodSig;
return ms is null ? false : ms.HasThis;
}
}
///
/// true if the method has an explicit 'this' parameter
///
public bool ExplicitThis {
get {
var ms = MethodSig;
return ms is null ? false : ms.ExplicitThis;
}
}
///
/// Gets the calling convention
///
public CallingConvention CallingConvention {
get {
var ms = MethodSig;
return ms is null ? 0 : ms.CallingConvention & CallingConvention.Mask;
}
}
///
/// Gets/sets the method return type
///
public TypeSig ReturnType {
get => MethodSig?.RetType;
set {
var ms = MethodSig;
if (ms is not null)
ms.RetType = value;
}
}
///
/// true if the method returns a value (i.e., return type is not )
///
public bool HasReturnType => ReturnType.RemovePinnedAndModifiers().GetElementType() != ElementType.Void;
///
/// Gets/sets the method semantics attributes. If you remove/add a method to a property or
/// an event, you must manually update this property or eg. won't
/// work as expected.
///
public MethodSemanticsAttributes SemanticsAttributes {
get {
if ((semAttrs & SEMATTRS_INITD) == 0)
InitializeSemanticsAttributes();
return (MethodSemanticsAttributes)semAttrs;
}
set => semAttrs = (ushort)value | SEMATTRS_INITD;
}
/// Set when has been initialized
protected internal static int SEMATTRS_INITD = unchecked((int)0x80000000);
///
protected internal int semAttrs;
/// Initializes
protected virtual void InitializeSemanticsAttributes() => semAttrs = 0 | SEMATTRS_INITD;
///
/// Set or clear flags in
///
/// true if flags should be set, false if flags should
/// be cleared
/// Flags to set or clear
void ModifyAttributes(bool set, MethodSemanticsAttributes flags) {
if ((semAttrs & SEMATTRS_INITD) == 0)
InitializeSemanticsAttributes();
if (set)
semAttrs |= (int)flags;
else
semAttrs &= ~(int)flags;
}
///
/// Modify property: =
/// ( & ) | .
///
/// Value to AND
/// Value to OR
void ModifyAttributes(MethodAttributes andMask, MethodAttributes orMask) =>
attributes = (attributes & (int)andMask) | (int)orMask;
///
/// Set or clear flags in
///
/// true if flags should be set, false if flags should
/// be cleared
/// Flags to set or clear
void ModifyAttributes(bool set, MethodAttributes flags) {
if (set)
attributes |= (int)flags;
else
attributes &= ~(int)flags;
}
///
/// Modify property: =
/// ( & ) | .
///
/// Value to AND
/// Value to OR
void ModifyImplAttributes(MethodImplAttributes andMask, MethodImplAttributes orMask) =>
implAttributes = (implAttributes & (int)andMask) | (int)orMask;
///
/// Set or clear flags in
///
/// true if flags should be set, false if flags should
/// be cleared
/// Flags to set or clear
void ModifyImplAttributes(bool set, MethodImplAttributes flags) {
if (set)
implAttributes |= (int)flags;
else
implAttributes &= ~(int)flags;
}
///
/// Gets/sets the method access
///
public MethodAttributes Access {
get => (MethodAttributes)attributes & MethodAttributes.MemberAccessMask;
set => ModifyAttributes(~MethodAttributes.MemberAccessMask, value & MethodAttributes.MemberAccessMask);
}
///
/// true if is set
///
public bool IsCompilerControlled => IsPrivateScope;
///
/// true if is set
///
public bool IsPrivateScope => ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
///
/// true if is set
///
public bool IsPrivate => ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Private;
///
/// true if is set
///
public bool IsFamilyAndAssembly => ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamANDAssem;
///
/// true if is set
///
public bool IsAssembly => ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Assembly;
///
/// true if is set
///
public bool IsFamily => ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Family;
///
/// true if is set
///
public bool IsFamilyOrAssembly => ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.FamORAssem;
///
/// true if is set
///
public bool IsPublic => ((MethodAttributes)attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public;
///
/// Gets/sets the bit
///
public bool IsStatic {
get => ((MethodAttributes)attributes & MethodAttributes.Static) != 0;
set => ModifyAttributes(value, MethodAttributes.Static);
}
///
/// Gets/sets the bit
///
public bool IsFinal {
get => ((MethodAttributes)attributes & MethodAttributes.Final) != 0;
set => ModifyAttributes(value, MethodAttributes.Final);
}
///
/// Gets/sets the bit
///
public bool IsVirtual {
get => ((MethodAttributes)attributes & MethodAttributes.Virtual) != 0;
set => ModifyAttributes(value, MethodAttributes.Virtual);
}
///
/// Gets/sets the bit
///
public bool IsHideBySig {
get => ((MethodAttributes)attributes & MethodAttributes.HideBySig) != 0;
set => ModifyAttributes(value, MethodAttributes.HideBySig);
}
///
/// Gets/sets the bit
///
public bool IsNewSlot {
get => ((MethodAttributes)attributes & MethodAttributes.NewSlot) != 0;
set => ModifyAttributes(value, MethodAttributes.NewSlot);
}
///
/// Gets/sets the bit
///
public bool IsReuseSlot {
get => ((MethodAttributes)attributes & MethodAttributes.NewSlot) == 0;
set => ModifyAttributes(!value, MethodAttributes.NewSlot);
}
///
/// Gets/sets the bit
///
public bool IsCheckAccessOnOverride {
get => ((MethodAttributes)attributes & MethodAttributes.CheckAccessOnOverride) != 0;
set => ModifyAttributes(value, MethodAttributes.CheckAccessOnOverride);
}
///
/// Gets/sets the bit
///
public bool IsAbstract {
get => ((MethodAttributes)attributes & MethodAttributes.Abstract) != 0;
set => ModifyAttributes(value, MethodAttributes.Abstract);
}
///
/// Gets/sets the bit
///
public bool IsSpecialName {
get => ((MethodAttributes)attributes & MethodAttributes.SpecialName) != 0;
set => ModifyAttributes(value, MethodAttributes.SpecialName);
}
///
/// Gets/sets the bit
///
public bool IsPinvokeImpl {
get => ((MethodAttributes)attributes & MethodAttributes.PinvokeImpl) != 0;
set => ModifyAttributes(value, MethodAttributes.PinvokeImpl);
}
///
/// Gets/sets the bit
///
public bool IsUnmanagedExport {
get => ((MethodAttributes)attributes & MethodAttributes.UnmanagedExport) != 0;
set => ModifyAttributes(value, MethodAttributes.UnmanagedExport);
}
///
/// Gets/sets the bit
///
public bool IsRuntimeSpecialName {
get => ((MethodAttributes)attributes & MethodAttributes.RTSpecialName) != 0;
set => ModifyAttributes(value, MethodAttributes.RTSpecialName);
}
///
/// Gets/sets the bit
///
public bool HasSecurity {
get => ((MethodAttributes)attributes & MethodAttributes.HasSecurity) != 0;
set => ModifyAttributes(value, MethodAttributes.HasSecurity);
}
///
/// Gets/sets the bit
///
public bool IsRequireSecObject {
get => ((MethodAttributes)attributes & MethodAttributes.RequireSecObject) != 0;
set => ModifyAttributes(value, MethodAttributes.RequireSecObject);
}
///
/// Gets/sets the code type
///
public MethodImplAttributes CodeType {
get => (MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask;
set => ModifyImplAttributes(~MethodImplAttributes.CodeTypeMask, value & MethodImplAttributes.CodeTypeMask);
}
///
/// true if is set
///
public bool IsIL => ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.IL;
///
/// true if is set
///
public bool IsNative => ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.Native;
///
/// true if is set
///
public bool IsOPTIL => ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.OPTIL;
///
/// true if is set
///
public bool IsRuntime => ((MethodImplAttributes)implAttributes & MethodImplAttributes.CodeTypeMask) == MethodImplAttributes.Runtime;
///
/// Gets/sets the bit
///
public bool IsUnmanaged {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.Unmanaged) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.Unmanaged);
}
///
/// Gets/sets the bit
///
public bool IsManaged {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.Unmanaged) == 0;
set => ModifyImplAttributes(!value, MethodImplAttributes.Unmanaged);
}
///
/// Gets/sets the bit
///
public bool IsForwardRef {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.ForwardRef) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.ForwardRef);
}
///
/// Gets/sets the bit
///
public bool IsPreserveSig {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.PreserveSig) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.PreserveSig);
}
///
/// Gets/sets the bit
///
public bool IsInternalCall {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.InternalCall) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.InternalCall);
}
///
/// Gets/sets the bit
///
public bool IsSynchronized {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.Synchronized) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.Synchronized);
}
///
/// Gets/sets the bit
///
public bool IsNoInlining {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.NoInlining) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.NoInlining);
}
///
/// Gets/sets the bit
///
public bool IsAggressiveInlining {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.AggressiveInlining) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.AggressiveInlining);
}
///
/// Gets/sets the bit
///
public bool IsNoOptimization {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.NoOptimization) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.NoOptimization);
}
///
/// Gets/sets the bit
///
public bool IsAggressiveOptimization {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.AggressiveOptimization) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.AggressiveOptimization);
}
///
/// Gets/sets the bit
///
public bool HasSecurityMitigations {
get => ((MethodImplAttributes)implAttributes & MethodImplAttributes.SecurityMitigations) != 0;
set => ModifyImplAttributes(value, MethodImplAttributes.SecurityMitigations);
}
///
/// Gets/sets the bit
///
public bool IsSetter {
get => (SemanticsAttributes & MethodSemanticsAttributes.Setter) != 0;
set => ModifyAttributes(value, MethodSemanticsAttributes.Setter);
}
///
/// Gets/sets the bit
///
public bool IsGetter {
get => (SemanticsAttributes & MethodSemanticsAttributes.Getter) != 0;
set => ModifyAttributes(value, MethodSemanticsAttributes.Getter);
}
///
/// Gets/sets the bit
///
public bool IsOther {
get => (SemanticsAttributes & MethodSemanticsAttributes.Other) != 0;
set => ModifyAttributes(value, MethodSemanticsAttributes.Other);
}
///
/// Gets/sets the bit
///
public bool IsAddOn {
get => (SemanticsAttributes & MethodSemanticsAttributes.AddOn) != 0;
set => ModifyAttributes(value, MethodSemanticsAttributes.AddOn);
}
///
/// Gets/sets the bit
///
public bool IsRemoveOn {
get => (SemanticsAttributes & MethodSemanticsAttributes.RemoveOn) != 0;
set => ModifyAttributes(value, MethodSemanticsAttributes.RemoveOn);
}
///
/// Gets/sets the bit
///
public bool IsFire {
get => (SemanticsAttributes & MethodSemanticsAttributes.Fire) != 0;
set => ModifyAttributes(value, MethodSemanticsAttributes.Fire);
}
///
/// true if this is the static type constructor
///
public bool IsStaticConstructor => IsRuntimeSpecialName && UTF8String.Equals(name, StaticConstructorName);
///
/// true if this is an instance constructor
///
public bool IsInstanceConstructor => IsRuntimeSpecialName && UTF8String.Equals(name, InstanceConstructorName);
///
/// true if this is a static or an instance constructor
///
public bool IsConstructor => IsStaticConstructor || IsInstanceConstructor;
///
void IListListener.OnLazyAdd(int index, ref GenericParam value) => OnLazyAdd2(index, ref value);
internal virtual void OnLazyAdd2(int index, ref GenericParam value) {
#if DEBUG
if (value.Owner != this)
throw new InvalidOperationException("Added generic param's Owner != this");
#endif
}
///
void IListListener.OnAdd(int index, GenericParam value) {
if (value.Owner is not null)
throw new InvalidOperationException("Generic param is already owned by another type/method. Set Owner to null first.");
value.Owner = this;
}
///
void IListListener.OnRemove(int index, GenericParam value) => value.Owner = null;
///
void IListListener.OnResize(int index) {
}
///
void IListListener.OnClear() {
foreach (var gp in genericParameters.GetEnumerable_NoLock())
gp.Owner = null;
}
///
void IListListener.OnLazyAdd(int index, ref ParamDef value) => OnLazyAdd2(index, ref value);
internal virtual void OnLazyAdd2(int index, ref ParamDef value) {
#if DEBUG
if (value.DeclaringMethod != this)
throw new InvalidOperationException("Added param's DeclaringMethod != this");
#endif
}
///
void IListListener.OnAdd(int index, ParamDef value) {
if (value.DeclaringMethod is not null)
throw new InvalidOperationException("Param is already owned by another method. Set DeclaringMethod to null first.");
value.DeclaringMethod = this;
}
///
void IListListener.OnRemove(int index, ParamDef value) => value.DeclaringMethod = null;
///
void IListListener.OnResize(int index) {
}
///
void IListListener.OnClear() {
foreach (var pd in paramDefs.GetEnumerable_NoLock())
pd.DeclaringMethod = null;
}
///
public override string ToString() => FullName;
}
///
/// A Method row created by the user and not present in the original .NET file
///
public class MethodDefUser : MethodDef {
///
/// Default constructor
///
public MethodDefUser() {
paramDefs = new LazyList(this);
genericParameters = new LazyList(this);
parameterList = new ParameterList(this, null);
semAttrs = 0 | SEMATTRS_INITD;
}
///
/// Constructor
///
/// Method name
public MethodDefUser(UTF8String name)
: this(name, null, 0, 0) {
}
///
/// Constructor
///
/// Method name
/// Method sig
public MethodDefUser(UTF8String name, MethodSig methodSig)
: this(name, methodSig, 0, 0) {
}
///
/// Constructor
///
/// Method name
/// Method sig
/// Flags
public MethodDefUser(UTF8String name, MethodSig methodSig, MethodAttributes flags)
: this(name, methodSig, 0, flags) {
}
///
/// Constructor
///
/// Method name
/// Method sig
/// Impl flags
public MethodDefUser(UTF8String name, MethodSig methodSig, MethodImplAttributes implFlags)
: this(name, methodSig, implFlags, 0) {
}
///
/// Constructor
///
/// Method name
/// Method sig
/// Impl flags
/// Flags
public MethodDefUser(UTF8String name, MethodSig methodSig, MethodImplAttributes implFlags, MethodAttributes flags) {
this.name = name;
signature = methodSig;
paramDefs = new LazyList(this);
genericParameters = new LazyList(this);
implAttributes = (int)implFlags;
attributes = (int)flags;
parameterList = new ParameterList(this, null);
semAttrs = 0 | SEMATTRS_INITD;
}
}
///
/// Created from a row in the Method table
///
sealed class MethodDefMD : MethodDef, IMDTokenProviderMD {
/// The module where this instance is located
readonly ModuleDefMD readerModule;
readonly uint origRid;
readonly RVA origRva;
readonly MethodImplAttributes origImplAttributes;
///
public uint OrigRid => origRid;
///
protected override void InitializeParamDefs() {
var list = readerModule.Metadata.GetParamRidList(origRid);
var tmp = new LazyList(list.Count, this, list, (list2, index) => readerModule.ResolveParam(list2[index]));
Interlocked.CompareExchange(ref paramDefs, tmp, null);
}
///
protected override void InitializeGenericParameters() {
var list = readerModule.Metadata.GetGenericParamRidList(Table.Method, origRid);
var tmp = new LazyList(list.Count, this, list, (list2, index) => readerModule.ResolveGenericParam(list2[index]));
Interlocked.CompareExchange(ref genericParameters, tmp, null);
}
///
protected override void InitializeDeclSecurities() {
var list = readerModule.Metadata.GetDeclSecurityRidList(Table.Method, origRid);
var tmp = new LazyList(list.Count, list, (list2, index) => readerModule.ResolveDeclSecurity(list2[index]));
Interlocked.CompareExchange(ref declSecurities, tmp, null);
}
///
protected override ImplMap GetImplMap_NoLock() => readerModule.ResolveImplMap(readerModule.Metadata.GetImplMapRid(Table.Method, origRid));
///
protected override MethodBody GetMethodBody_NoLock() => readerModule.ReadMethodBody(this, origRva, origImplAttributes, new GenericParamContext(declaringType2, this));
///
protected override void InitializeCustomAttributes() {
var list = readerModule.Metadata.GetCustomAttributeRidList(Table.Method, origRid);
var tmp = new CustomAttributeCollection(list.Count, list, (list2, index) => readerModule.ReadCustomAttribute(list[index]));
Interlocked.CompareExchange(ref customAttributes, tmp, null);
}
///
protected override void InitializeCustomDebugInfos() {
var list = new List();
if (Interlocked.CompareExchange(ref customDebugInfos, list, null) is null) {
var body = Body;
readerModule.InitializeCustomDebugInfos(this, body, list);
}
}
///
protected override void InitializeOverrides() {
var dt = declaringType2 as TypeDefMD;
var tmp = dt is null ? new List() : dt.GetMethodOverrides(this, new GenericParamContext(declaringType2, this));
Interlocked.CompareExchange(ref overrides, tmp, null);
}
///
protected override void InitializeSemanticsAttributes() {
if (DeclaringType is TypeDefMD dt)
dt.InitializeMethodSemanticsAttributes();
semAttrs |= SEMATTRS_INITD;
}
///
/// Constructor
///
/// The module which contains this Method row
/// Row ID
/// If is null
/// If is invalid
public MethodDefMD(ModuleDefMD readerModule, uint rid) {
#if DEBUG
if (readerModule is null)
throw new ArgumentNullException("readerModule");
if (readerModule.TablesStream.MethodTable.IsInvalidRID(rid))
throw new BadImageFormatException($"Method rid {rid} does not exist");
#endif
origRid = rid;
this.rid = rid;
this.readerModule = readerModule;
bool b = readerModule.TablesStream.TryReadMethodRow(origRid, out var row);
Debug.Assert(b);
rva = (RVA)row.RVA;
implAttributes = row.ImplFlags;
attributes = row.Flags;
name = readerModule.StringsStream.ReadNoNull(row.Name);
origRva = rva;
origImplAttributes = (MethodImplAttributes)implAttributes;
declaringType2 = readerModule.GetOwnerType(this);
signature = readerModule.ReadSignature(row.Signature, new GenericParamContext(declaringType2, this));
parameterList = new ParameterList(this, declaringType2);
exportInfo = readerModule.GetExportInfo(rid);
}
internal MethodDefMD InitializeAll() {
MemberMDInitializer.Initialize(RVA);
MemberMDInitializer.Initialize(Attributes);
MemberMDInitializer.Initialize(ImplAttributes);
MemberMDInitializer.Initialize(Name);
MemberMDInitializer.Initialize(Signature);
MemberMDInitializer.Initialize(ImplMap);
MemberMDInitializer.Initialize(MethodBody);
MemberMDInitializer.Initialize(DeclaringType);
MemberMDInitializer.Initialize(CustomAttributes);
MemberMDInitializer.Initialize(Overrides);
MemberMDInitializer.Initialize(ParamDefs);
MemberMDInitializer.Initialize(GenericParameters);
MemberMDInitializer.Initialize(DeclSecurities);
return this;
}
///
internal override void OnLazyAdd2(int index, ref GenericParam value) {
if (value.Owner != this) {
// More than one owner... This module has invalid metadata.
value = readerModule.ForceUpdateRowId(readerModule.ReadGenericParam(value.Rid).InitializeAll());
value.Owner = this;
}
}
///
internal override void OnLazyAdd2(int index, ref ParamDef value) {
if (value.DeclaringMethod != this) {
// More than one owner... This module has invalid metadata.
value = readerModule.ForceUpdateRowId(readerModule.ReadParam(value.Rid).InitializeAll());
value.DeclaringMethod = this;
}
}
}
}