|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Diagnostics.SymbolStore;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
namespace System.Reflection.Emit
{
internal sealed class ModuleBuilderImpl : ModuleBuilder
{
private readonly Assembly _coreAssembly;
private readonly string _name;
private readonly MetadataBuilder _metadataBuilder;
private readonly PersistedAssemblyBuilder _assemblyBuilder;
private readonly TypeBuilderImpl _globalTypeBuilder;
private readonly Dictionary<Assembly, AssemblyReferenceHandle> _assemblyReferences = new();
private readonly Dictionary<Type, EntityHandle> _typeReferences = new();
private readonly Dictionary<object, EntityHandle> _memberReferences = new();
private readonly List<TypeBuilderImpl> _typeDefinitions = new();
private readonly Guid _moduleVersionId;
private Dictionary<string, ModuleReferenceHandle>? _moduleReferences;
private List<CustomAttributeWrapper>? _customAttributes;
private Dictionary<SymbolDocumentWriter, DocumentHandle> _docHandles = new();
private int _nextTypeDefRowId = 1;
private int _nextMethodDefRowId = 1;
private int _nextFieldDefRowId = 1;
private int _nextParameterRowId = 1;
private int _nextPropertyRowId = 1;
private int _nextEventRowId = 1;
private bool _coreTypesFullyPopulated;
private bool _hasGlobalBeenCreated;
private Type?[]? _coreTypes;
private MetadataBuilder _pdbBuilder = new();
// The order of the types should match with the CoreTypeId enum values order.
private static readonly Type[] s_coreTypes = { typeof(void), typeof(object), typeof(bool), typeof(char), typeof(sbyte),
typeof(byte), typeof(short), typeof(ushort), typeof(int), typeof(uint),
typeof(long), typeof(ulong), typeof(float), typeof(double), typeof(string),
typeof(nint), typeof(nuint), typeof(TypedReference), typeof(ValueType) };
internal ModuleBuilderImpl(string name, Assembly coreAssembly, MetadataBuilder builder, PersistedAssemblyBuilder assemblyBuilder)
{
_coreAssembly = coreAssembly;
_name = name;
_metadataBuilder = builder;
_assemblyBuilder = assemblyBuilder;
_moduleVersionId = Guid.NewGuid();
_globalTypeBuilder = new TypeBuilderImpl(this);
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Types are preserved via s_coreTypes")]
internal Type GetTypeFromCoreAssembly(CoreTypeId typeId)
{
if (_coreTypes == null)
{
// Use s_coreTypes directly for runtime reflection
if (_coreAssembly == typeof(object).Assembly)
{
_coreTypes = s_coreTypes;
_coreTypesFullyPopulated = true;
}
else
{
_coreTypes = new Type[s_coreTypes.Length];
}
}
int index = (int)typeId;
return _coreTypes[index] ?? (_coreTypes[index] = _coreAssembly.GetType(s_coreTypes[index].FullName!, throwOnError: true)!);
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Types are preserved via s_coreTypes")]
internal CoreTypeId? GetTypeIdFromCoreTypes(Type type)
{
if (_coreTypes == null)
{
// Use s_coreTypes directly for runtime reflection
if (_coreAssembly == typeof(object).Assembly)
{
_coreTypes = s_coreTypes;
_coreTypesFullyPopulated = true;
}
else
{
_coreTypes = new Type[s_coreTypes.Length];
}
}
if (!_coreTypesFullyPopulated)
{
for (int i = 0; i < _coreTypes.Length; i++)
{
if (_coreTypes[i] == null)
{
_coreTypes[i] = _coreAssembly.GetType(s_coreTypes[i].FullName!, throwOnError: false)!;
}
}
_coreTypesFullyPopulated = true;
}
for (int i = 0; i < _coreTypes.Length; i++)
{
if (_coreTypes[i] == type)
{
return (CoreTypeId)i;
}
}
return null;
}
internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder, BlobBuilder fieldDataBuilder, out MetadataBuilder pdbBuilder)
{
// Add module metadata
ModuleDefinitionHandle moduleHandle = _metadataBuilder.AddModule(
generation: 0,
moduleName: _metadataBuilder.GetOrAddString(_name),
mvid: _metadataBuilder.GetOrAddGuid(_moduleVersionId),
encId: default,
encBaseId: default);
// Create type definition for the special <Module> type that holds global functions
_metadataBuilder.AddTypeDefinition(
attributes: default,
@namespace: default,
name: _metadataBuilder.GetOrAddString("<Module>"),
baseType: default,
fieldList: MetadataTokens.FieldDefinitionHandle(1),
methodList: MetadataTokens.MethodDefinitionHandle(1));
WriteCustomAttributes(_customAttributes, moduleHandle);
// All generic parameters for all types and methods should be written in specific order
List<GenericTypeParameterBuilderImpl> genericParams = new();
PopulateTokensForTypesAndItsMembers();
// Add global members
WriteFields(_globalTypeBuilder, fieldDataBuilder);
WriteMethods(_globalTypeBuilder._methodDefinitions, genericParams, methodBodyEncoder);
// Add each type definition to metadata table.
foreach (TypeBuilderImpl typeBuilder in _typeDefinitions)
{
typeBuilder.ThrowIfNotCreated();
EntityHandle parent = default;
if (typeBuilder.BaseType is not null)
{
parent = GetTypeHandle(typeBuilder.BaseType);
}
TypeDefinitionHandle typeHandle = AddTypeDefinition(typeBuilder, parent, typeBuilder._firstMethodToken, typeBuilder._firstFieldToken);
Debug.Assert(typeBuilder._handle.Equals(typeHandle));
if (typeBuilder.IsGenericType)
{
foreach (GenericTypeParameterBuilderImpl param in typeBuilder.GenericTypeParameters)
{
param._parentHandle = typeHandle;
genericParams.Add(param);
}
}
if ((typeBuilder.Attributes & TypeAttributes.ExplicitLayout) != 0)
{
_metadataBuilder.AddTypeLayout(typeHandle, (ushort)typeBuilder.PackingSize, (uint)typeBuilder.Size);
}
if (typeBuilder.DeclaringType != null)
{
_metadataBuilder.AddNestedType(typeHandle, (TypeDefinitionHandle)GetTypeHandle(typeBuilder.DeclaringType));
}
WriteInterfaceImplementations(typeBuilder, typeHandle);
WriteCustomAttributes(typeBuilder._customAttributes, typeHandle);
WriteProperties(typeBuilder);
WriteFields(typeBuilder, fieldDataBuilder);
WriteMethods(typeBuilder._methodDefinitions, genericParams, methodBodyEncoder);
WriteEvents(typeBuilder);
}
// Now write all generic parameters in order
genericParams.Sort((x, y) => {
int primary = CodedIndex.TypeOrMethodDef(x._parentHandle).CompareTo(CodedIndex.TypeOrMethodDef(y._parentHandle));
if (primary != 0)
return primary;
return x.GenericParameterPosition.CompareTo(y.GenericParameterPosition);
});
foreach (GenericTypeParameterBuilderImpl param in genericParams)
{
AddGenericTypeParametersAndConstraintsCustomAttributes(param._parentHandle, param);
}
pdbBuilder = _pdbBuilder;
}
private void WriteInterfaceImplementations(TypeBuilderImpl typeBuilder, TypeDefinitionHandle typeHandle)
{
if (typeBuilder._interfaces != null)
{
foreach (Type iface in typeBuilder._interfaces)
{
_metadataBuilder.AddInterfaceImplementation(typeHandle, GetTypeHandle(iface));
}
}
// Even there were no interfaces implemented it could have an override for base type abstract method
if (typeBuilder._methodOverrides != null)
{
foreach (List<(MethodInfo ifaceMethod, MethodInfo targetMethod)> mapList in typeBuilder._methodOverrides.Values)
{
foreach ((MethodInfo ifaceMethod, MethodInfo targetMethod) pair in mapList)
{
_metadataBuilder.AddMethodImplementation(typeHandle, GetMemberHandle(pair.targetMethod), GetMemberHandle(pair.ifaceMethod));
}
}
}
}
private void WriteEvents(TypeBuilderImpl typeBuilder)
{
if (typeBuilder._eventDefinitions.Count == 0)
{
return;
}
AddEventMap(typeBuilder._handle, typeBuilder._firstEventToken);
foreach (EventBuilderImpl eventBuilder in typeBuilder._eventDefinitions)
{
EventDefinitionHandle eventHandle = AddEventDefinition(eventBuilder, GetTypeHandle(eventBuilder.EventType));
WriteCustomAttributes(eventBuilder._customAttributes, eventHandle);
if (eventBuilder._addOnMethod is MethodBuilderImpl aMb)
{
AddMethodSemantics(eventHandle, MethodSemanticsAttributes.Adder, aMb._handle);
}
if (eventBuilder._raiseMethod is MethodBuilderImpl rMb)
{
AddMethodSemantics(eventHandle, MethodSemanticsAttributes.Raiser, rMb._handle);
}
if (eventBuilder._removeMethod is MethodBuilderImpl remMb)
{
AddMethodSemantics(eventHandle, MethodSemanticsAttributes.Remover, remMb._handle);
}
if (eventBuilder._otherMethods != null)
{
foreach (MethodBuilderImpl method in eventBuilder._otherMethods)
{
AddMethodSemantics(eventHandle, MethodSemanticsAttributes.Other, method._handle);
}
}
}
}
private void WriteProperties(TypeBuilderImpl typeBuilder)
{
if (typeBuilder._propertyDefinitions.Count == 0)
{
return;
}
AddPropertyMap(typeBuilder._handle, typeBuilder._firstPropertyToken);
foreach (PropertyBuilderImpl property in typeBuilder._propertyDefinitions)
{
PropertyDefinitionHandle propertyHandle = AddPropertyDefinition(property, MetadataSignatureHelper.GetPropertySignature(property, this));
WriteCustomAttributes(property._customAttributes, propertyHandle);
if (property.GetMethod is MethodBuilderImpl gMb)
{
AddMethodSemantics(propertyHandle, MethodSemanticsAttributes.Getter, gMb._handle);
}
if (property.SetMethod is MethodBuilderImpl sMb)
{
AddMethodSemantics(propertyHandle, MethodSemanticsAttributes.Setter, sMb._handle);
}
if (property._otherMethods != null)
{
foreach (MethodBuilderImpl method in property._otherMethods)
{
AddMethodSemantics(propertyHandle, MethodSemanticsAttributes.Other, method._handle);
}
}
if (property._defaultValue != DBNull.Value)
{
AddDefaultValue(propertyHandle, property._defaultValue);
}
}
}
private void PopulateFieldDefinitionHandles(List<FieldBuilderImpl> fieldDefinitions)
{
foreach (FieldBuilderImpl field in fieldDefinitions)
{
field._handle = MetadataTokens.FieldDefinitionHandle(_nextFieldDefRowId++);
}
}
private void PopulateMethodDefinitionHandles(List<MethodBuilderImpl> methods)
{
foreach (MethodBuilderImpl method in methods)
{
method._handle = MetadataTokens.MethodDefinitionHandle(_nextMethodDefRowId++);
}
}
private void PopulatePropertyDefinitionHandles(List<PropertyBuilderImpl> properties)
{
foreach (PropertyBuilderImpl property in properties)
{
property._handle = MetadataTokens.PropertyDefinitionHandle(_nextPropertyRowId++);
}
}
private void PopulateEventDefinitionHandles(List<EventBuilderImpl> eventDefinitions)
{
foreach (EventBuilderImpl eventBuilder in eventDefinitions)
{
eventBuilder._handle = MetadataTokens.EventDefinitionHandle(_nextEventRowId++);
}
}
private void PopulateTokensForTypesAndItsMembers()
{
foreach (TypeBuilderImpl typeBuilder in _typeDefinitions)
{
typeBuilder._handle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId);
typeBuilder._firstMethodToken = _nextMethodDefRowId;
typeBuilder._firstFieldToken = _nextFieldDefRowId;
typeBuilder._firstPropertyToken = _nextPropertyRowId;
typeBuilder._firstEventToken = _nextEventRowId;
PopulateMethodDefinitionHandles(typeBuilder._methodDefinitions);
PopulateFieldDefinitionHandles(typeBuilder._fieldDefinitions);
PopulatePropertyDefinitionHandles(typeBuilder._propertyDefinitions);
PopulateEventDefinitionHandles(typeBuilder._eventDefinitions);
}
}
private void WriteMethods(List<MethodBuilderImpl> methods, List<GenericTypeParameterBuilderImpl> genericParams,
MethodBodyStreamEncoder methodBodyEncoder)
{
foreach (MethodBuilderImpl method in methods)
{
int offset = -1;
ILGeneratorImpl? il = method.ILGeneratorImpl;
if (il != null)
{
FillMemberReferences(il);
il.AddExceptionBlocks();
StandaloneSignatureHandle signature = il.LocalCount == 0 ? default :
_metadataBuilder.AddStandaloneSignature(_metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.GetLocalSignature(il.Locals, this)));
offset = AddMethodBody(method, il, signature, methodBodyEncoder);
AddSymbolInfo(il, signature, method._handle);
}
MethodDefinitionHandle handle = AddMethodDefinition(method, method.GetMethodSignatureBlob(), offset, _nextParameterRowId);
Debug.Assert(method._handle == handle);
WriteCustomAttributes(method._customAttributes, handle);
if (method.IsGenericMethodDefinition)
{
Type[] gParams = method.GetGenericArguments();
for (int i = 0; i < gParams.Length; i++)
{
GenericTypeParameterBuilderImpl param = (GenericTypeParameterBuilderImpl)gParams[i];
param._parentHandle = handle;
genericParams.Add(param);
}
}
if (method._parameterBuilders != null)
{
foreach (ParameterBuilderImpl parameter in method._parameterBuilders)
{
if (parameter != null)
{
ParameterHandle parameterHandle = AddParameter(parameter);
WriteCustomAttributes(parameter._customAttributes, parameterHandle);
_nextParameterRowId++;
if (parameter._marshallingData != null)
{
AddMarshalling(parameterHandle, parameter._marshallingData.SerializeMarshallingData());
}
if (parameter._defaultValue != DBNull.Value)
{
AddDefaultValue(parameterHandle, parameter._defaultValue);
}
}
}
}
if (method._dllImportData != null)
{
AddMethodImport(handle, method._dllImportData.EntryPoint ?? method.Name,
method._dllImportData.Flags, GetModuleReference(method._dllImportData.ModuleName));
}
}
}
private void AddSymbolInfo(ILGeneratorImpl il, StandaloneSignatureHandle localSignatureHandle, MethodDefinitionHandle methodHandle)
{
if (il.DocumentToSequencePoints.Count == 0)
{
// empty sequence point
_pdbBuilder.AddMethodDebugInformation(default, default);
}
else
{
Dictionary<SymbolDocumentWriter, List<SequencePoint>>.Enumerator enumerator = il.DocumentToSequencePoints.GetEnumerator();
if (il.DocumentToSequencePoints.Count > 1)
{
// sequence points spans multiple docs
_pdbBuilder.AddMethodDebugInformation(default, PopulateMultiDocSequencePointsBlob(enumerator, localSignatureHandle));
}
else // single document sequence point
{
int previousNonHiddenStartLine = -1;
int previousNonHiddenStartColumn = -1;
enumerator.MoveNext();
BlobBuilder spBlobBuilder = new BlobBuilder();
spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(localSignatureHandle));
PopulateSequencePointsBlob(spBlobBuilder, enumerator.Current.Value, ref previousNonHiddenStartLine, ref previousNonHiddenStartColumn);
_pdbBuilder.AddMethodDebugInformation(GetDocument(enumerator.Current.Key), _pdbBuilder.GetOrAddBlob(spBlobBuilder));
}
}
Scope scope = il.Scope;
scope._endOffset = il.ILOffset; // Outer most scope covers the entire method body, so haven't closed by the user.
AddLocalScope(methodHandle, parentImport: default, MetadataTokens.LocalVariableHandle(_pdbBuilder.GetRowCount(TableIndex.LocalVariable) + 1), scope);
}
private BlobHandle PopulateMultiDocSequencePointsBlob(Dictionary<SymbolDocumentWriter, List<SequencePoint>>.Enumerator enumerator, StandaloneSignatureHandle localSignature)
{
BlobBuilder spBlobBuilder = new BlobBuilder();
int previousNonHiddenStartLine = -1;
int previousNonHiddenStartColumn = -1;
enumerator.MoveNext();
KeyValuePair<SymbolDocumentWriter, List<SequencePoint>> pair = enumerator.Current;
// header:
spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(localSignature));
spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(GetDocument(pair.Key)));
// First sequence point record
PopulateSequencePointsBlob(spBlobBuilder, pair.Value, ref previousNonHiddenStartLine, ref previousNonHiddenStartColumn);
while (enumerator.MoveNext())
{
pair = enumerator.Current;
spBlobBuilder.WriteCompressedInteger(0);
spBlobBuilder.WriteCompressedInteger(MetadataTokens.GetRowNumber(GetDocument(pair.Key)));
PopulateSequencePointsBlob(spBlobBuilder, pair.Value, ref previousNonHiddenStartLine, ref previousNonHiddenStartColumn);
}
return _pdbBuilder.GetOrAddBlob(spBlobBuilder);
}
private static void PopulateSequencePointsBlob(BlobBuilder spBlobBuilder, List<SequencePoint> sequencePoints, ref int previousNonHiddenStartLine, ref int previousNonHiddenStartColumn)
{
for (int i = 0; i < sequencePoints.Count; i++)
{
// IL offset delta:
if (i > 0)
{
spBlobBuilder.WriteCompressedInteger(sequencePoints[i].Offset - sequencePoints[i - 1].Offset);
}
else
{
spBlobBuilder.WriteCompressedInteger(sequencePoints[i].Offset);
}
if (sequencePoints[i].IsHidden)
{
spBlobBuilder.WriteUInt16(0);
continue;
}
// Delta Lines & Columns:
SerializeDeltaLinesAndColumns(spBlobBuilder, sequencePoints[i]);
// delta Start Lines & Columns:
if (previousNonHiddenStartLine < 0)
{
Debug.Assert(previousNonHiddenStartColumn < 0);
spBlobBuilder.WriteCompressedInteger(sequencePoints[i].StartLine);
spBlobBuilder.WriteCompressedInteger(sequencePoints[i].StartColumn);
}
else
{
spBlobBuilder.WriteCompressedSignedInteger(sequencePoints[i].StartLine - previousNonHiddenStartLine);
spBlobBuilder.WriteCompressedSignedInteger(sequencePoints[i].StartColumn - previousNonHiddenStartColumn);
}
previousNonHiddenStartLine = sequencePoints[i].StartLine;
previousNonHiddenStartColumn = sequencePoints[i].StartColumn;
}
}
private void AddLocalScope(MethodDefinitionHandle methodHandle, ImportScopeHandle parentImport, LocalVariableHandle firstLocalVariableHandle, Scope scope)
{
parentImport = GetImportScopeHandle(scope._importNamespaces, parentImport);
firstLocalVariableHandle = GetLocalVariableHandle(scope._locals, firstLocalVariableHandle);
_pdbBuilder.AddLocalScope(methodHandle, parentImport, firstLocalVariableHandle,
constantList: MetadataTokens.LocalConstantHandle(1), scope._startOffset, scope._endOffset - scope._startOffset);
if (scope._children != null)
{
foreach (Scope childScope in scope._children)
{
AddLocalScope(methodHandle, parentImport, MetadataTokens.LocalVariableHandle(_pdbBuilder.GetRowCount(TableIndex.LocalVariable) + 1), childScope);
}
}
}
private LocalVariableHandle GetLocalVariableHandle(List<LocalBuilder>? locals, LocalVariableHandle firstLocalHandleOfLastScope)
{
if (locals != null)
{
bool firstLocalSet = false;
foreach (LocalBuilderImpl local in locals)
{
if (!string.IsNullOrEmpty(local.Name))
{
LocalVariableHandle localHandle = _pdbBuilder.AddLocalVariable(LocalVariableAttributes.None, local.LocalIndex,
local.Name == null ? _pdbBuilder.GetOrAddString(string.Empty) : _pdbBuilder.GetOrAddString(local.Name));
if (!firstLocalSet)
{
firstLocalHandleOfLastScope = localHandle;
firstLocalSet = true;
}
}
}
}
return firstLocalHandleOfLastScope;
}
private ImportScopeHandle GetImportScopeHandle(List<string>? importNamespaces, ImportScopeHandle parent)
{
if (importNamespaces == null)
{
return default;
}
BlobBuilder importBlob = new BlobBuilder();
foreach (string importNs in importNamespaces)
{
importBlob.WriteByte((byte)ImportDefinitionKind.ImportNamespace);
importBlob.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_pdbBuilder.GetOrAddBlobUTF8(importNs)));
}
return _pdbBuilder.AddImportScope(parent, _pdbBuilder.GetOrAddBlob(importBlob));
}
private static void SerializeDeltaLinesAndColumns(BlobBuilder spBuilder, SequencePoint sequencePoint)
{
int deltaLines = sequencePoint.EndLine - sequencePoint.StartLine;
int deltaColumns = sequencePoint.EndColumn - sequencePoint.StartColumn;
// only hidden sequence points have zero width
Debug.Assert(deltaLines != 0 || deltaColumns != 0 || sequencePoint.IsHidden);
spBuilder.WriteCompressedInteger(deltaLines);
if (deltaLines == 0)
{
spBuilder.WriteCompressedInteger(deltaColumns);
}
else
{
Debug.Assert(deltaLines > 0);
spBuilder.WriteCompressedSignedInteger(deltaColumns);
}
}
private DocumentHandle GetDocument(SymbolDocumentWriter docWriter)
{
if (!_docHandles.TryGetValue(docWriter, out DocumentHandle handle))
{
handle = AddDocument(docWriter.URL, docWriter.Language, docWriter.HashAlgorithm, docWriter.Hash);
_docHandles.Add(docWriter, handle);
}
return handle;
}
private DocumentHandle AddDocument(string url, Guid language, Guid hashAlgorithm, byte[]? hash) =>
_pdbBuilder.AddDocument(
name: _pdbBuilder.GetOrAddDocumentName(url),
hashAlgorithm: hashAlgorithm == default ? default : _pdbBuilder.GetOrAddGuid(hashAlgorithm),
hash: hash == null ? default : _pdbBuilder.GetOrAddBlob(hash),
language: language == default ? default : _pdbBuilder.GetOrAddGuid(language));
private void FillMemberReferences(ILGeneratorImpl il)
{
foreach (KeyValuePair<object, BlobWriter> pair in il.GetMemberReferences())
{
if (pair.Key is MemberInfo member)
{
pair.Value.WriteInt32(MetadataTokens.GetToken(GetMemberHandle(member)));
}
if (pair.Key is KeyValuePair<MethodInfo, Type[]> pair2)
{
pair.Value.WriteInt32(MetadataTokens.GetToken(GetMethodReference(pair2.Key, pair2.Value)));
}
}
}
private static int AddMethodBody(MethodBuilderImpl method, ILGeneratorImpl il, StandaloneSignatureHandle signature, MethodBodyStreamEncoder bodyEncoder) =>
bodyEncoder.AddMethodBody(
instructionEncoder: il.Instructions,
maxStack: il.GetMaxStack(),
localVariablesSignature: signature,
attributes: method.InitLocals ? MethodBodyAttributes.InitLocals : MethodBodyAttributes.None,
hasDynamicStackAllocation: il.HasDynamicStackAllocation);
private void WriteFields(TypeBuilderImpl typeBuilder, BlobBuilder fieldDataBuilder)
{
foreach (FieldBuilderImpl field in typeBuilder._fieldDefinitions)
{
FieldDefinitionHandle handle = AddFieldDefinition(field,
MetadataSignatureHelper.GetFieldSignature(field.FieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this));
Debug.Assert(field._handle == handle);
WriteCustomAttributes(field._customAttributes, handle);
if (field._offset >= 0 && (typeBuilder.Attributes & TypeAttributes.ExplicitLayout) != 0)
{
AddFieldLayout(handle, field._offset);
}
if (field.Attributes.HasFlag(FieldAttributes.HasFieldMarshal) && field._marshallingData != null)
{
AddMarshalling(handle, field._marshallingData.SerializeMarshallingData());
}
if (field.Attributes.HasFlag(FieldAttributes.HasDefault) && field._defaultValue != DBNull.Value)
{
AddDefaultValue(handle, field._defaultValue);
}
if (field.Attributes.HasFlag(FieldAttributes.HasFieldRVA) && field._rvaData != null)
{
_metadataBuilder.AddFieldRelativeVirtualAddress(handle, fieldDataBuilder.Count);
fieldDataBuilder.WriteBytes(field._rvaData!);
fieldDataBuilder.Align(ManagedPEBuilder.MappedFieldDataAlignment);
}
}
}
private ModuleReferenceHandle GetModuleReference(string moduleName)
{
_moduleReferences ??= new Dictionary<string, ModuleReferenceHandle>();
if (!_moduleReferences.TryGetValue(moduleName, out var handle))
{
handle = AddModuleReference(moduleName);
_moduleReferences.Add(moduleName, handle);
}
return handle;
}
internal void WriteCustomAttributes(List<CustomAttributeWrapper>? customAttributes, EntityHandle parent)
{
if (customAttributes != null)
{
foreach (CustomAttributeWrapper customAttribute in customAttributes)
{
_metadataBuilder.AddCustomAttribute(parent, GetMemberHandle(customAttribute.Ctor),
_metadataBuilder.GetOrAddBlob(customAttribute.Data));
}
}
}
private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type)
{
if (!_typeReferences.TryGetValue(type, out var typeHandle))
{
if (type.HasElementType || type.IsGenericParameter ||
(type.IsGenericType && !type.IsGenericTypeDefinition))
{
typeHandle = AddTypeSpecification(type);
}
else
{
if (type.IsNested)
{
typeHandle = AddTypeReference(GetTypeReferenceOrSpecificationHandle(type.DeclaringType!), null, type.Name);
}
else
{
typeHandle = AddTypeReference(GetAssemblyReference(type.Assembly), type.Namespace, type.Name);
}
}
_typeReferences.Add(type, typeHandle);
}
return typeHandle;
}
private TypeSpecificationHandle AddTypeSpecification(Type type) =>
_metadataBuilder.AddTypeSpecification(
signature: _metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.GetTypeSpecificationSignature(type, this)));
private MethodSpecificationHandle AddMethodSpecification(EntityHandle methodHandle, Type[] genericArgs) =>
_metadataBuilder.AddMethodSpecification(
method: methodHandle,
instantiation: _metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.GetMethodSpecificationSignature(genericArgs, this)));
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:RequiresDynamicCode", Justification = "Test")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:RequiresUnreferencedCode", Justification = "Test")]
private EntityHandle GetMemberReferenceHandle(MemberInfo memberInfo)
{
if (!_memberReferences.TryGetValue(memberInfo, out var memberHandle))
{
switch (memberInfo)
{
case FieldInfo field:
Type declaringType = field.DeclaringType!;
if (declaringType.IsGenericTypeDefinition)
{
//The type of the field has to be fully instantiated type.
declaringType = declaringType.MakeGenericType(declaringType.GetGenericArguments());
}
Type fieldType = ((FieldInfo)GetOriginalMemberIfConstructedType(field)).FieldType;
memberHandle = AddMemberReference(field.Name, GetTypeHandle(declaringType),
MetadataSignatureHelper.GetFieldSignature(fieldType, field.GetRequiredCustomModifiers(), field.GetOptionalCustomModifiers(), this));
break;
case ConstructorInfo ctor:
ctor = (ConstructorInfo)GetOriginalMemberIfConstructedType(ctor);
memberHandle = AddMemberReference(ctor.Name, GetTypeHandle(memberInfo.DeclaringType!), MetadataSignatureHelper.GetConstructorSignature(ctor.GetParameters(), this));
break;
case MethodInfo method:
if (method.IsConstructedGenericMethod)
{
memberHandle = AddMethodSpecification(GetMemberHandle(method.GetGenericMethodDefinition()), method.GetGenericArguments());
}
else if (method is ArrayMethod sm)
{
memberHandle = AddMemberReference(sm.Name, GetTypeHandle(sm.DeclaringType!), GetMethodArrayMethodSignature(sm));
}
else
{
method = (MethodInfo)GetOriginalMemberIfConstructedType(method);
memberHandle = AddMemberReference(method.Name, GetTypeHandle(memberInfo.DeclaringType!), GetMethodSignature(method, null));
}
break;
default:
throw new NotSupportedException();
}
_memberReferences.Add(memberInfo, memberHandle);
}
return memberHandle;
}
private EntityHandle GetMethodReference(MethodInfo methodInfo, Type[] optionalParameterTypes)
{
MethodInfo method = (MethodInfo)GetOriginalMemberIfConstructedType(methodInfo);
BlobBuilder signature = GetMethodSignature(method, optionalParameterTypes);
KeyValuePair<MethodInfo, BlobBuilder> pair = new(method, signature);
if (!_memberReferences.TryGetValue(pair, out var memberHandle))
{
memberHandle = AddMemberReference(method.Name, GetMemberHandle(method), signature);
_memberReferences.Add(pair, memberHandle);
}
return memberHandle;
}
private BlobBuilder GetMethodSignature(MethodInfo method, Type[]? optionalParameterTypes) =>
MetadataSignatureHelper.GetMethodSignature(this, ParameterTypes(method.GetParameters()), method.ReturnType,
GetSignatureConvention(method.CallingConvention), method.GetGenericArguments().Length, !method.IsStatic, optionalParameterTypes);
private BlobBuilder GetMethodArrayMethodSignature(ArrayMethod method) => MetadataSignatureHelper.GetMethodSignature(
this, method.ParameterTypes, method.ReturnType, GetSignatureConvention(method.CallingConvention), isInstance: IsInstance(method.CallingConvention));
private static bool IsInstance(CallingConventions callingConvention) =>
callingConvention.HasFlag(CallingConventions.HasThis) || callingConvention.HasFlag(CallingConventions.ExplicitThis) ? true : false;
internal static SignatureCallingConvention GetSignatureConvention(CallingConventions callingConvention)
{
SignatureCallingConvention convention = SignatureCallingConvention.Default;
if ((callingConvention & CallingConventions.VarArgs) != 0)
{
convention = SignatureCallingConvention.VarArgs;
}
return convention;
}
private MemberInfo GetOriginalMemberIfConstructedType(MemberInfo memberInfo)
{
Type declaringType = memberInfo.DeclaringType!;
if (declaringType.IsConstructedGenericType &&
declaringType.GetGenericTypeDefinition() is not TypeBuilderImpl &&
!ContainsTypeBuilder(declaringType.GetGenericArguments()))
{
return declaringType.GetGenericTypeDefinition().GetMemberWithSameMetadataDefinitionAs(memberInfo);
}
return memberInfo;
}
private static Type[] ParameterTypes(ParameterInfo[] parameterInfos)
{
if (parameterInfos.Length == 0)
{
return Type.EmptyTypes;
}
Type[] parameterTypes = new Type[parameterInfos.Length];
for (int i = 0; i < parameterInfos.Length; i++)
{
parameterTypes[i] = parameterInfos[i].ParameterType;
}
return parameterTypes;
}
private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly)
{
if (!_assemblyReferences.TryGetValue(assembly, out var handle))
{
AssemblyName aName = assembly.GetName();
// For ref assembly flags shall have only one bit set, the PublicKey bit.
// All other bits shall be zero. See ECMA-335 spec II.22.5
AssemblyFlags assemblyFlags = 0;
byte[]? publicKeyOrToken = aName.GetPublicKey();
if (publicKeyOrToken != null && publicKeyOrToken.Length > 0)
{
assemblyFlags = AssemblyFlags.PublicKey;
}
else
{
publicKeyOrToken = aName.GetPublicKeyToken();
}
handle = AddAssemblyReference(aName.Name, aName.Version, aName.CultureName, publicKeyOrToken, assemblyFlags);
_assemblyReferences.Add(assembly, handle);
}
return handle;
}
private void AddGenericTypeParametersAndConstraintsCustomAttributes(EntityHandle parentHandle, GenericTypeParameterBuilderImpl gParam)
{
GenericParameterHandle handle = _metadataBuilder.AddGenericParameter(
parent: parentHandle,
attributes: gParam.GenericParameterAttributes,
name: _metadataBuilder.GetOrAddString(gParam.Name),
index: gParam.GenericParameterPosition);
WriteCustomAttributes(gParam._customAttributes, handle);
foreach (Type constraint in gParam.GetGenericParameterConstraints())
{
_metadataBuilder.AddGenericParameterConstraint(handle, GetTypeHandle(constraint));
}
}
private void AddDefaultValue(EntityHandle parentHandle, object? defaultValue)
{
if (defaultValue != null)
{
Type type = defaultValue.GetType();
if (type.IsEnum)
{
// ECMA spec II.22.9: in case of enum the constant type shall match the underlying type of that enum.
defaultValue = Convert.ChangeType(defaultValue, type.GetEnumUnderlyingType());
}
}
_metadataBuilder.AddConstant(parent: parentHandle, value: defaultValue);
}
private void AddMethodSemantics(EntityHandle parentHandle, MethodSemanticsAttributes attribute, MethodDefinitionHandle methodHandle) =>
_metadataBuilder.AddMethodSemantics(
association: parentHandle,
semantics: attribute,
methodDefinition: methodHandle);
private PropertyDefinitionHandle AddPropertyDefinition(PropertyBuilderImpl property, BlobBuilder signature) =>
_metadataBuilder.AddProperty(
attributes: property.Attributes,
name: _metadataBuilder.GetOrAddString(property.Name),
signature: _metadataBuilder.GetOrAddBlob(signature));
private EventDefinitionHandle AddEventDefinition(EventBuilderImpl eventBuilder, EntityHandle eventType) =>
_metadataBuilder.AddEvent(
attributes: eventBuilder.Attributes,
name: _metadataBuilder.GetOrAddString(eventBuilder.Name),
type: eventType);
private void AddEventMap(TypeDefinitionHandle typeHandle, int firstEventToken) =>
_metadataBuilder.AddEventMap(
declaringType: typeHandle,
eventList: MetadataTokens.EventDefinitionHandle(firstEventToken));
private void AddPropertyMap(TypeDefinitionHandle typeHandle, int firstPropertyToken) =>
_metadataBuilder.AddPropertyMap(
declaringType: typeHandle,
propertyList: MetadataTokens.PropertyDefinitionHandle(firstPropertyToken));
private FieldDefinitionHandle AddFieldDefinition(FieldBuilderImpl field, BlobBuilder fieldSignature) =>
_metadataBuilder.AddFieldDefinition(
attributes: field.Attributes,
name: _metadataBuilder.GetOrAddString(field.Name),
signature: _metadataBuilder.GetOrAddBlob(fieldSignature));
private TypeDefinitionHandle AddTypeDefinition(TypeBuilderImpl type, EntityHandle parent, int methodToken, int fieldToken) =>
_metadataBuilder.AddTypeDefinition(
attributes: type.Attributes,
@namespace: (type.Namespace == null) ? default : _metadataBuilder.GetOrAddString(type.Namespace),
name: _metadataBuilder.GetOrAddString(type.Name),
baseType: parent,
fieldList: MetadataTokens.FieldDefinitionHandle(fieldToken),
methodList: MetadataTokens.MethodDefinitionHandle(methodToken));
private MethodDefinitionHandle AddMethodDefinition(MethodBuilderImpl method, BlobBuilder methodSignature, int offset, int parameterToken) =>
_metadataBuilder.AddMethodDefinition(
attributes: method.Attributes,
implAttributes: method.GetMethodImplementationFlags(),
name: _metadataBuilder.GetOrAddString(method.Name),
signature: _metadataBuilder.GetOrAddBlob(methodSignature),
bodyOffset: offset,
parameterList: MetadataTokens.ParameterHandle(parameterToken));
private TypeReferenceHandle AddTypeReference(EntityHandle resolutionScope, string? ns, string name) =>
_metadataBuilder.AddTypeReference(
resolutionScope: resolutionScope,
@namespace: (ns == null) ? default : _metadataBuilder.GetOrAddString(ns),
name: _metadataBuilder.GetOrAddString(name));
private MemberReferenceHandle AddMemberReference(string memberName, EntityHandle parent, BlobBuilder signature) =>
_metadataBuilder.AddMemberReference(
parent: parent,
name: _metadataBuilder.GetOrAddString(memberName),
signature: _metadataBuilder.GetOrAddBlob(signature));
private void AddMethodImport(MethodDefinitionHandle methodHandle, string name,
MethodImportAttributes attributes, ModuleReferenceHandle moduleHandle) =>
_metadataBuilder.AddMethodImport(
method: methodHandle,
attributes: attributes,
name: _metadataBuilder.GetOrAddString(name),
module: moduleHandle);
private ModuleReferenceHandle AddModuleReference(string moduleName) =>
_metadataBuilder.AddModuleReference(moduleName: _metadataBuilder.GetOrAddString(moduleName));
private void AddFieldLayout(FieldDefinitionHandle fieldHandle, int offset) =>
_metadataBuilder.AddFieldLayout(field: fieldHandle, offset: offset);
private void AddMarshalling(EntityHandle parent, BlobBuilder builder) =>
_metadataBuilder.AddMarshallingDescriptor(parent: parent, descriptor: _metadataBuilder.GetOrAddBlob(builder));
private ParameterHandle AddParameter(ParameterBuilderImpl parameter) =>
_metadataBuilder.AddParameter(
attributes: (ParameterAttributes)parameter.Attributes,
name: parameter.Name != null ? _metadataBuilder.GetOrAddString(parameter.Name) : default,
sequenceNumber: parameter.Position);
private AssemblyReferenceHandle AddAssemblyReference(string? name, Version? version, string? culture,
byte[]? publicKeyToken, AssemblyFlags assemblyFlags) =>
_metadataBuilder.AddAssemblyReference(
name: name == null ? default : _metadataBuilder.GetOrAddString(name),
version: version ?? new Version(0, 0, 0, 0),
culture: (culture == null) ? default : _metadataBuilder.GetOrAddString(value: culture),
publicKeyOrToken: (publicKeyToken == null) ? default : _metadataBuilder.GetOrAddBlob(publicKeyToken),
flags: assemblyFlags,
hashValue: default); // .file directive assemblies not supported, no need to handle this value.
internal EntityHandle GetTypeHandle(Type type)
{
if (type is TypeBuilderImpl tb && Equals(tb.Module))
{
Debug.Assert(tb.IsCreated());
return tb._handle;
}
if (type is EnumBuilderImpl eb && Equals(eb.Module))
{
Debug.Assert(eb._typeBuilder.IsCreated());
return eb._typeBuilder._handle;
}
return GetTypeReferenceOrSpecificationHandle(type);
}
internal EntityHandle GetMemberHandle(MemberInfo member)
{
if (member is TypeBuilderImpl tb && Equals(tb.Module))
{
return tb._handle;
}
if (member is EnumBuilderImpl en && Equals(en.Module))
{
return en._typeBuilder._handle;
}
if (member is Type type)
{
return GetTypeReferenceOrSpecificationHandle(type);
}
if (member is MethodBuilderImpl mb && Equals(mb.Module))
{
return mb._handle;
}
if (member is ConstructorBuilderImpl ctor && Equals(ctor.Module))
{
return ctor._methodBuilder._handle;
}
if (member is FieldBuilderImpl fb && Equals(fb.Module) && !fb.DeclaringType!.IsGenericTypeDefinition)
{
return fb._handle;
}
if (member is PropertyBuilderImpl prop && Equals(prop.Module))
{
return prop._handle;
}
return GetMemberReferenceHandle(member);
}
internal TypeBuilder DefineNestedType(string name, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent,
Type[]? interfaces, PackingSize packingSize, int typesize, TypeBuilderImpl? enclosingType)
{
TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, interfaces, packingSize, typesize, enclosingType);
_typeDefinitions.Add(_type);
return _type;
}
[RequiresAssemblyFiles("Returns <Unknown> for modules with no file path")]
public override string Name => "<In Memory Module>";
public override string ScopeName => _name;
public override Assembly Assembly => _assemblyBuilder;
public override Guid ModuleVersionId => _moduleVersionId;
public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();
public override int GetFieldMetadataToken(FieldInfo field) => GetTokenForHandle(TryGetFieldHandle(field));
internal EntityHandle TryGetFieldHandle(FieldInfo field)
{
if (field is FieldBuilderImpl fb && Equals(fb.Module))
{
return fb._handle;
}
return GetHandleForMember(field);
}
private static int GetTokenForHandle(EntityHandle handle)
{
if (handle.IsNil)
{
throw new InvalidOperationException(SR.InvalidOperation_TokenNotPopulated);
}
return MetadataTokens.GetToken(handle);
}
private EntityHandle GetHandleForMember(MemberInfo member)
{
if (IsConstructedFromTypeBuilder(member.DeclaringType!))
{
return default;
}
return GetMemberReferenceHandle(member);
}
private bool IsConstructedFromTypeBuilder(Type type)
{
if (type.IsConstructedGenericType)
{
return (type.GetGenericTypeDefinition() is TypeBuilderImpl tb && Equals(tb.Module)) ||
ContainsTypeBuilder(type.GetGenericArguments());
}
if (type.HasElementType)
{
Type elementType = type.GetElementType()!;
return (elementType is TypeBuilderImpl tbi && Equals(tbi.Module)) || IsConstructedFromTypeBuilder(elementType);
}
return false;
}
internal bool ContainsTypeBuilder(Type[] genericArguments)
{
foreach (Type type in genericArguments)
{
if ((type is TypeBuilderImpl tb && Equals(tb.Module)) || (type is GenericTypeParameterBuilderImpl gtb && Equals(gtb.Module)))
{
return true;
}
if (IsConstructedFromTypeBuilder(type))
{
return true;
}
}
return false;
}
internal EntityHandle TryGetTypeHandle(Type type)
{
if (type is TypeBuilderImpl tb && Equals(tb.Module))
{
return tb._handle;
}
if (type is EnumBuilderImpl eb && Equals(eb.Module))
{
return eb._typeBuilder._handle;
}
if (IsConstructedFromTypeBuilder(type))
{
return default;
}
return GetTypeReferenceOrSpecificationHandle(type);
}
public override int GetMethodMetadataToken(ConstructorInfo constructor) => GetTokenForHandle(TryGetConstructorHandle(constructor));
internal EntityHandle TryGetConstructorHandle(ConstructorInfo constructor)
{
if (constructor is ConstructorBuilderImpl cb && Equals(cb.Module))
{
return cb._methodBuilder._handle;
}
return GetHandleForMember(constructor);
}
public override int GetMethodMetadataToken(MethodInfo method) => GetTokenForHandle(TryGetMethodHandle(method));
internal EntityHandle TryGetMethodHandle(MethodInfo method)
{
if (method is MethodBuilderImpl mb && Equals(mb.Module))
{
return mb._handle;
}
if (IsConstructedFromMethodBuilderOrTypeBuilder(method) ||
IsArrayMethodTypeIsTypeBuilder(method))
{
return default;
}
return GetHandleForMember(method);
}
private bool IsArrayMethodTypeIsTypeBuilder(MethodInfo method) => method is ArrayMethod arrayMethod &&
arrayMethod.DeclaringType!.GetElementType() is TypeBuilderImpl tb && Equals(tb.Module);
private bool IsConstructedFromMethodBuilderOrTypeBuilder(MethodInfo method) => method.IsConstructedGenericMethod &&
((method.GetGenericMethodDefinition() is MethodBuilderImpl mb && Equals(mb.Module)) || ContainsTypeBuilder(method.GetGenericArguments()));
internal EntityHandle TryGetMethodHandle(MethodInfo method, Type[] optionalParameterTypes)
{
if ((method.CallingConvention & CallingConventions.VarArgs) == 0)
{
// Client should not supply optional parameter in default calling convention
throw new InvalidOperationException(SR.InvalidOperation_NotAVarArgCallingConvention);
}
if (method is MethodBuilderImpl mb && Equals(mb.Module))
{
return mb._handle;
}
if (IsConstructedFromMethodBuilderOrTypeBuilder(method))
{
return default;
}
return GetMethodReference(method, optionalParameterTypes);
}
internal TypeBuilderImpl? FindTypeBuilderWithName(string strTypeName, bool ignoreCase)
{
StringComparison casing = ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal;
foreach (TypeBuilderImpl type in _typeDefinitions)
{
if (string.Equals(type.Name, strTypeName, casing))
{
return type;
}
}
return null;
}
public override int GetStringMetadataToken(string stringConstant) => MetadataTokens.GetToken(_metadataBuilder.GetOrAddUserString(stringConstant));
public override int GetTypeMetadataToken(Type type) => GetTokenForHandle(TryGetTypeHandle(type));
protected override void CreateGlobalFunctionsCore()
{
if (_hasGlobalBeenCreated)
{
throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated);
}
_globalTypeBuilder.CreateTypeInfo();
_hasGlobalBeenCreated = true;
}
protected override EnumBuilder DefineEnumCore(string name, TypeAttributes visibility, Type underlyingType)
{
EnumBuilderImpl enumBuilder = new EnumBuilderImpl(name, underlyingType, visibility, this);
_typeDefinitions.Add(enumBuilder._typeBuilder);
return enumBuilder;
}
protected override MethodBuilder DefineGlobalMethodCore(string name, MethodAttributes attributes, CallingConventions callingConvention,
Type? returnType, Type[]? requiredReturnTypeCustomModifiers, Type[]? optionalReturnTypeCustomModifiers, Type[]? parameterTypes,
Type[][]? requiredParameterTypeCustomModifiers, Type[][]? optionalParameterTypeCustomModifiers)
{
if (_hasGlobalBeenCreated)
{
throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated);
}
if ((attributes & MethodAttributes.Static) == 0)
{
throw new ArgumentException(SR.Argument_GlobalMembersMustBeStatic);
}
MethodBuilderImpl method = (MethodBuilderImpl)_globalTypeBuilder.DefineMethod(name, attributes, callingConvention,
returnType, requiredReturnTypeCustomModifiers, optionalReturnTypeCustomModifiers,
parameterTypes, requiredParameterTypeCustomModifiers, optionalParameterTypeCustomModifiers);
method._handle = MetadataTokens.MethodDefinitionHandle(_nextMethodDefRowId++);
return method;
}
protected override FieldBuilder DefineInitializedDataCore(string name, byte[] data, FieldAttributes attributes)
{
if (_hasGlobalBeenCreated)
{
throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated);
}
FieldBuilderImpl field = (FieldBuilderImpl)_globalTypeBuilder.DefineInitializedData(name, data, attributes);
field._handle = MetadataTokens.FieldDefinitionHandle(_nextFieldDefRowId++);
return field;
}
[RequiresUnreferencedCode("P/Invoke marshalling may dynamically access members that could be trimmed.")]
protected override MethodBuilder DefinePInvokeMethodCore(string name, string dllName, string entryName, MethodAttributes attributes,
CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet)
{
// Global methods must be static.
if ((attributes & MethodAttributes.Static) == 0)
{
throw new ArgumentException(SR.Argument_GlobalMembersMustBeStatic);
}
MethodBuilderImpl method = (MethodBuilderImpl)_globalTypeBuilder.DefinePInvokeMethod(
name, dllName, entryName, attributes, callingConvention, returnType, parameterTypes, nativeCallConv, nativeCharSet);
method._handle = MetadataTokens.MethodDefinitionHandle(_nextMethodDefRowId++);
return method;
}
protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize)
{
TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, interfaces, packingSize, typesize, null);
_typeDefinitions.Add(_type);
return _type;
}
protected override FieldBuilder DefineUninitializedDataCore(string name, int size, FieldAttributes attributes)
{
if (_hasGlobalBeenCreated)
{
throw new InvalidOperationException(SR.InvalidOperation_GlobalsHaveBeenCreated);
}
FieldBuilderImpl field = (FieldBuilderImpl)_globalTypeBuilder.DefineUninitializedData(name, size, attributes);
field._handle = MetadataTokens.FieldDefinitionHandle(_nextFieldDefRowId++);
return field;
}
protected override MethodInfo GetArrayMethodCore(Type arrayClass, string methodName,
CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes)
{
if (!arrayClass.IsArray)
{
throw new ArgumentException(SR.Argument_HasToBeArrayClass);
}
// GetArrayMethod is useful when you have an array of a type whose definition has not been completed and
// you want to access methods defined on Array. For example, you might define a type and want to define a
// method that takes an array of the type as a parameter. In order to access the elements of the array,
// you will need to call methods of the Array class.
return new ArrayMethod(this, arrayClass, methodName, callingConvention, returnType, parameterTypes);
}
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
_customAttributes ??= new List<CustomAttributeWrapper>();
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
[RequiresUnreferencedCode("Methods might be removed")]
protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder,
CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers)
{
if (types == null)
{
return _globalTypeBuilder.GetMethod(name, bindingAttr);
}
return _globalTypeBuilder.GetMethod(name, bindingAttr, binder, callConvention, types, modifiers);
}
[RequiresUnreferencedCode("Methods might be removed")]
public override MethodInfo[] GetMethods(BindingFlags bindingFlags)
{
return _globalTypeBuilder.GetMethods(bindingFlags);
}
public override int GetSignatureMetadataToken(SignatureHelper signature) =>
MetadataTokens.GetToken(_metadataBuilder.AddStandaloneSignature(_metadataBuilder.GetOrAddBlob(signature.GetSignature())));
internal int GetSignatureToken(CallingConventions callingConventions, Type? returnType, Type[]? parameterTypes, Type[]? optionalParameterTypes) =>
MetadataTokens.GetToken(_metadataBuilder.AddStandaloneSignature(
_metadataBuilder.GetOrAddBlob(MetadataSignatureHelper.GetMethodSignature(this, parameterTypes, returnType,
GetSignatureConvention(callingConventions), optionalParameterTypes: optionalParameterTypes))));
internal int GetSignatureToken(CallingConvention callingConvention, Type? returnType, Type[]? parameterTypes) =>
MetadataTokens.GetToken(_metadataBuilder.AddStandaloneSignature(_metadataBuilder.GetOrAddBlob(
MetadataSignatureHelper.GetMethodSignature(this, parameterTypes, returnType, GetSignatureConvention(callingConvention)))));
private static SignatureCallingConvention GetSignatureConvention(CallingConvention callingConvention) =>
callingConvention switch
{
CallingConvention.Winapi => SignatureCallingConvention.Default, // TODO: platform-specific
CallingConvention.Cdecl => SignatureCallingConvention.CDecl,
CallingConvention.StdCall => SignatureCallingConvention.StdCall,
CallingConvention.ThisCall => SignatureCallingConvention.ThisCall,
CallingConvention.FastCall => SignatureCallingConvention.FastCall,
_ => SignatureCallingConvention.Default,
};
protected override ISymbolDocumentWriter DefineDocumentCore(string url, Guid language = default)
{
return new SymbolDocumentWriter(url, language);
}
internal List<TypeBuilderImpl> GetNestedTypeBuilders(TypeBuilderImpl declaringType)
{
List<TypeBuilderImpl> nestedTypes = new List<TypeBuilderImpl>();
foreach (TypeBuilderImpl typeBuilder in _typeDefinitions)
{
if (typeBuilder.DeclaringType == declaringType)
{
nestedTypes.Add(typeBuilder);
}
}
return nestedTypes;
}
}
}
|