Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make System.Reflection.Emit public types abstract #78544

Merged
merged 45 commits into from
Jan 27, 2023
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
d8d444d
Add abstract AssemblyBuilder
jkotas Feb 2, 2022
97ed454
Create managed RuntimeAssemblyBuilder
jkotas Feb 6, 2022
791b4cb
Add RuntimeAssemblyBuilder to the build
jkotas Feb 6, 2022
eaa8c73
Boilerplate for RuntimeAssemblyBuilder
jkotas Feb 8, 2022
80c310d
Emit Assembly record
jkotas Feb 9, 2022
c82c7d0
Fixups after rebase
jkotas Feb 9, 2022
85b37d6
Add temporary ReflectionEmitLoadContext
jkotas Feb 9, 2022
cde27c2
Factor out RuntimeModuleBuilder
jkotas Feb 9, 2022
6fe4240
Abstract TypeBuilder and EventBuilder
jkotas Mar 23, 2022
79dd71a
Refactor PropertyBuilder
jkotas Mar 25, 2022
7ec068b
Refactor EnumBuilder
jkotas Mar 25, 2022
b36778c
Refactor FieldBuilder
jkotas Mar 25, 2022
6ee8a67
Refactor ConstructorBuilder and MethodBuilder
jkotas Mar 25, 2022
e127952
Fix app compat issues
buyaa-n Nov 10, 2022
e102000
Revert updates that not needed for initial step
buyaa-n Nov 16, 2022
c32f0e5
Make GenericTypeParameterBuilder abstract
buyaa-n Nov 18, 2022
3b4cba9
Merge conflicts
buyaa-n Nov 18, 2022
0bbcaa7
Fix errors found after merge
buyaa-n Nov 18, 2022
9b96074
Fix app compat issue
buyaa-n Nov 18, 2022
8dcc68d
Merge remote-tracking branch 'upstream/main' into reflection-emit
ViktorHofer Nov 22, 2022
9017148
Move suppressions into the common file
ViktorHofer Nov 22, 2022
a8bf9f2
Update mono implementations
buyaa-n Dec 9, 2022
bab5062
Merge conflicts
buyaa-n Dec 9, 2022
c8a2574
Merge conflicts
buyaa-n Dec 9, 2022
0383fc6
Handle API compat warnings
buyaa-n Dec 9, 2022
b656b01
Fix some failures
buyaa-n Dec 12, 2022
fe0fddf
Mono updates
buyaa-n Dec 13, 2022
3433e5a
Mono updates
buyaa-n Dec 20, 2022
a6928a5
Merge branch 'main' of https://github.com/dotnet/runtime into reflect…
buyaa-n Dec 21, 2022
902f550
Suppress unused variable warning
buyaa-n Dec 21, 2022
a6f202e
Mono failure fixes
buyaa-n Dec 28, 2022
ceb7230
Check ModuleBuilder from generic arguments
buyaa-n Dec 29, 2022
9de8783
Update src/mono/System.Private.CoreLib/src/System/Reflection/Emit/Typ…
buyaa-n Dec 29, 2022
9f07478
Keep runtime old behavior for TypeBuilder static methods
buyaa-n Dec 29, 2022
c4287ae
Merge branch 'reflection-emit' of github.com:buyaa-n/runtime into ref…
buyaa-n Dec 29, 2022
6c1e9ed
Remove/revert some unwanted changes
buyaa-n Jan 3, 2023
dd90d0a
Merge branch 'main' of https://github.com/dotnet/runtime into reflect…
buyaa-n Jan 4, 2023
522d3a7
Merge branch 'main' of https://github.com/dotnet/runtime into reflect…
buyaa-n Jan 5, 2023
a348398
Remove unneeded change
buyaa-n Jan 6, 2023
24f5298
Apply latest feedback
buyaa-n Jan 20, 2023
eeab882
Merge conflict
buyaa-n Jan 20, 2023
34c0216
Use protected absract methods and other related changes
buyaa-n Jan 23, 2023
98ca969
Apply feedback and latest API review updates, refert compat suppressions
buyaa-n Jan 25, 2023
039a89a
Add Assert
buyaa-n Jan 26, 2023
a16ce6e
Fix API compat failures
buyaa-n Jan 27, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,60 @@

namespace System.Reflection.Emit
{
public sealed partial class AssemblyBuilder : Assembly
public partial class AssemblyBuilder
{
[RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")]
[DynamicSecurityMethod] // Required to make Assembly.GetCallingAssembly reliable.
public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)
=> DefineDynamicAssembly(name, access, null, Assembly.GetCallingAssembly());

[RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")]
[DynamicSecurityMethod] // Required to make Assembly.GetCallingAssembly reliable.
public static AssemblyBuilder DefineDynamicAssembly(
AssemblyName name,
AssemblyBuilderAccess access,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
=> DefineDynamicAssembly(name, access, assemblyAttributes, Assembly.GetCallingAssembly());

private static AssemblyBuilder DefineDynamicAssembly(
AssemblyName name,
AssemblyBuilderAccess access,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes,
Assembly? callingAssembly)
{
ArgumentNullException.ThrowIfNull(name);

if (access != AssemblyBuilderAccess.Run && access != AssemblyBuilderAccess.RunAndCollect)
{
throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)access), nameof(access));
}

if (callingAssembly == null)
{
// Called either from interop or async delegate invocation. Rejecting because we don't
// know how to set the correct context of the new dynamic assembly.
throw new InvalidOperationException();
}

AssemblyLoadContext? assemblyLoadContext =
AssemblyLoadContext.CurrentContextualReflectionContext ?? AssemblyLoadContext.GetLoadContext(callingAssembly);

if (assemblyLoadContext == null)
{
throw new InvalidOperationException();
}

return new RuntimeAssemblyBuilder(name, access, assemblyLoadContext, assemblyAttributes);
}
}

internal sealed partial class RuntimeAssemblyBuilder : AssemblyBuilder
{
#region Internal Data Members

internal readonly AssemblyBuilderAccess _access;
private readonly RuntimeAssembly _internalAssembly;
private readonly ModuleBuilder _manifestModuleBuilder;
private readonly RuntimeModuleBuilder _manifestModuleBuilder;
// Set to true if the manifest module was returned by code:DefineDynamicModule to the user
private bool _isManifestModuleUsedAsDefinedModule;

Expand All @@ -37,35 +84,21 @@ public sealed partial class AssemblyBuilder : Assembly

#region Constructor

internal AssemblyBuilder(AssemblyName name,
internal RuntimeAssemblyBuilder(AssemblyName name,
AssemblyBuilderAccess access,
Assembly? callingAssembly,
AssemblyLoadContext? assemblyLoadContext,
AssemblyLoadContext assemblyLoadContext,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
{
ArgumentNullException.ThrowIfNull(name);

if (access != AssemblyBuilderAccess.Run && access != AssemblyBuilderAccess.RunAndCollect)
{
throw new ArgumentException(SR.Format(SR.Arg_EnumIllegalVal, (int)access), nameof(access));
}
if (callingAssembly == null)
{
// Called either from interop or async delegate invocation. Rejecting because we don't
// know how to set the correct context of the new dynamic assembly.
throw new InvalidOperationException();
}

_access = access;

_internalAssembly = CreateDynamicAssembly(assemblyLoadContext ?? AssemblyLoadContext.GetLoadContext(callingAssembly)!, name, access);
_internalAssembly = CreateDynamicAssembly(assemblyLoadContext, name, access);

// Make sure that ManifestModule is properly initialized
// We need to do this before setting any CustomAttribute
// Note that this ModuleBuilder cannot be used for RefEmit yet
// because it hasn't been initialized.
// However, it can be used to set the custom attribute on the Assembly
_manifestModuleBuilder = new ModuleBuilder(this, (RuntimeModule)InternalAssembly.ManifestModule);
_manifestModuleBuilder = new RuntimeModuleBuilder(this, (RuntimeModule)InternalAssembly.ManifestModule);

if (assemblyAttributes != null)
{
Expand All @@ -80,31 +113,6 @@ public sealed partial class AssemblyBuilder : Assembly

#region DefineDynamicAssembly

[RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")]
[DynamicSecurityMethod] // Required to make Assembly.GetCallingAssembly reliable.
public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access)
{
return InternalDefineDynamicAssembly(name,
access,
Assembly.GetCallingAssembly(),
AssemblyLoadContext.CurrentContextualReflectionContext,
null);
}

[RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")]
[DynamicSecurityMethod] // Required to make Assembly.GetCallingAssembly reliable.
public static AssemblyBuilder DefineDynamicAssembly(
AssemblyName name,
AssemblyBuilderAccess access,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
{
return InternalDefineDynamicAssembly(name,
access,
Assembly.GetCallingAssembly(),
AssemblyLoadContext.CurrentContextualReflectionContext,
assemblyAttributes);
}

[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "AppDomain_CreateDynamicAssembly")]
private static unsafe partial void CreateDynamicAssembly(ObjectHandleOnStack assemblyLoadContext,
NativeAssemblyNameParts* pAssemblyName,
Expand Down Expand Up @@ -147,19 +155,17 @@ private static unsafe RuntimeAssembly CreateDynamicAssembly(AssemblyLoadContext

private static readonly object s_assemblyBuilderLock = new object();

internal static AssemblyBuilder InternalDefineDynamicAssembly(
internal static RuntimeAssemblyBuilder InternalDefineDynamicAssembly(
AssemblyName name,
AssemblyBuilderAccess access,
Assembly? callingAssembly,
AssemblyLoadContext? assemblyLoadContext,
AssemblyLoadContext assemblyLoadContext,
IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
{
lock (s_assemblyBuilderLock)
{
// We can only create dynamic assemblies in the current domain
return new AssemblyBuilder(name,
return new RuntimeAssemblyBuilder(name,
access,
callingAssembly,
assemblyLoadContext,
assemblyAttributes);
}
Expand All @@ -173,7 +179,7 @@ private static unsafe RuntimeAssembly CreateDynamicAssembly(AssemblyLoadContext
/// modules within an Assembly with the same name. This dynamic module is
/// a transient module.
/// </summary>
public ModuleBuilder DefineDynamicModule(string name)
public override ModuleBuilder DefineDynamicModule(string name)
{
lock (SyncRoot)
{
Expand Down Expand Up @@ -211,10 +217,6 @@ internal void CheckTypeNameConflict(string strTypeName, TypeBuilder? enclosingTy
_manifestModuleBuilder.CheckTypeNameConflict(strTypeName, enclosingType);
}

public override bool Equals(object? obj) => base.Equals(obj);

public override int GetHashCode() => base.GetHashCode();

#region ICustomAttributeProvider Members
public override object[] GetCustomAttributes(bool inherit) =>
InternalAssembly.GetCustomAttributes(inherit);
Expand Down Expand Up @@ -273,22 +275,13 @@ internal void CheckTypeNameConflict(string strTypeName, TypeBuilder? enclosingTy

/// <param name="name">The name of module for the look up.</param>
/// <returns>Dynamic module with the specified name.</returns>
public ModuleBuilder? GetDynamicModule(string name)
{
lock (SyncRoot)
{
return GetDynamicModuleNoLock(name);
}
}

/// <param name="name">The name of module for the look up.</param>
private ModuleBuilder? GetDynamicModuleNoLock(string name)
public override ModuleBuilder? GetDynamicModule(string name)
{
ArgumentException.ThrowIfNullOrEmpty(name);

if (_isManifestModuleUsedAsDefinedModule)
{
if (ModuleBuilder.ManifestModuleName == name)
if (RuntimeModuleBuilder.ManifestModuleName == name)
{
return _manifestModuleBuilder;
}
Expand All @@ -299,14 +292,14 @@ internal void CheckTypeNameConflict(string strTypeName, TypeBuilder? enclosingTy
/// <summary>
/// Use this function if client decides to form the custom attribute blob themselves.
/// </summary>
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
public override void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
{
ArgumentNullException.ThrowIfNull(con);
ArgumentNullException.ThrowIfNull(binaryAttribute);

lock (SyncRoot)
{
TypeBuilder.DefineCustomAttribute(
RuntimeTypeBuilder.DefineCustomAttribute(
_manifestModuleBuilder, // pass in the in-memory assembly module
AssemblyDefToken,
_manifestModuleBuilder.GetConstructorToken(con),
Expand All @@ -317,7 +310,7 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
/// <summary>
/// Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder.
/// </summary>
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
public override void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@

namespace System.Reflection.Emit
{
public sealed class ConstructorBuilder : ConstructorInfo
internal sealed class RuntimeConstructorBuilder : ConstructorBuilder
buyaa-n marked this conversation as resolved.
Show resolved Hide resolved
{
private readonly MethodBuilder m_methodBuilder;
private readonly RuntimeMethodBuilder m_methodBuilder;
internal bool m_isDefaultConstructor;

#region Constructor

internal ConstructorBuilder(string name, MethodAttributes attributes, CallingConventions callingConvention,
Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers, ModuleBuilder mod, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TypeBuilder type)
internal RuntimeConstructorBuilder(string name, MethodAttributes attributes, CallingConventions callingConvention,
Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers, RuntimeModuleBuilder mod, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] RuntimeTypeBuilder type)
{
m_methodBuilder = new MethodBuilder(name, attributes, callingConvention, null, null, null,
m_methodBuilder = new RuntimeMethodBuilder(name, attributes, callingConvention, null, null, null,
parameterTypes, requiredCustomModifiers, optionalCustomModifiers, mod, type);

type.m_listMethods!.Add(m_methodBuilder);
Expand All @@ -26,8 +26,8 @@ public sealed class ConstructorBuilder : ConstructorInfo
_ = m_methodBuilder.MetadataToken; // Doubles as "CreateMethod" for MethodBuilder -- analogous to CreateType()
}

internal ConstructorBuilder(string name, MethodAttributes attributes, CallingConventions callingConvention,
Type[]? parameterTypes, ModuleBuilder mod, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TypeBuilder type) :
internal RuntimeConstructorBuilder(string name, MethodAttributes attributes, CallingConventions callingConvention,
Type[]? parameterTypes, RuntimeModuleBuilder mod, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] RuntimeTypeBuilder type) :
this(name, attributes, callingConvention, parameterTypes, null, null, mod, type)
{
}
Expand All @@ -41,7 +41,7 @@ internal override Type[] GetParameterTypes()
}

[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
private TypeBuilder GetTypeBuilder()
private RuntimeTypeBuilder GetTypeBuilder()
{
return m_methodBuilder.GetTypeBuilder();
}
Expand Down Expand Up @@ -122,7 +122,7 @@ public override bool IsDefined(Type attributeType, bool inherit)
#endregion

#region Public Members
public ParameterBuilder DefineParameter(int iSequence, ParameterAttributes attributes, string? strParamName)
public override ParameterBuilder DefineParameter(int iSequence, ParameterAttributes attributes, string? strParamName)
{
// Theoretically we shouldn't allow iSequence to be 0 because in reflection ctors don't have
// return parameters. But we'll allow it for backward compatibility with V2. The attributes
Expand All @@ -133,15 +133,15 @@ public ParameterBuilder DefineParameter(int iSequence, ParameterAttributes attri
return m_methodBuilder.DefineParameter(iSequence, attributes, strParamName);
}

public ILGenerator GetILGenerator()
public override ILGenerator GetILGenerator()
{
if (m_isDefaultConstructor)
throw new InvalidOperationException(SR.InvalidOperation_DefaultConstructorILGen);

return m_methodBuilder.GetILGenerator();
}

public ILGenerator GetILGenerator(int streamSize)
public override ILGenerator GetILGenerator(int streamSize)
{
if (m_isDefaultConstructor)
throw new InvalidOperationException(SR.InvalidOperation_DefaultConstructorILGen);
Expand All @@ -165,22 +165,22 @@ internal override Type GetReturnType()
return m_methodBuilder.ReturnType;
}

public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
public override void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
{
m_methodBuilder.SetCustomAttribute(con, binaryAttribute);
}

public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
public override void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
m_methodBuilder.SetCustomAttribute(customBuilder);
}

public void SetImplementationFlags(MethodImplAttributes attributes)
public override void SetImplementationFlags(MethodImplAttributes attributes)
{
m_methodBuilder.SetImplementationFlags(attributes);
}

public bool InitLocals
public override bool InitLocals
{
get => m_methodBuilder.InitLocals;
set => m_methodBuilder.InitLocals = value;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,14 @@ public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, Pr
// Might have failed check because one type is a XXXBuilder
// and the other is not. Deal with these special cases
// separately.
if (!TypeBuilder.IsTypeEqual(property.DeclaringType, con.DeclaringType))
if (!RuntimeTypeBuilder.IsTypeEqual(property.DeclaringType, con.DeclaringType))
{
// IsSubclassOf is overloaded to do the right thing if
// the constructor is a TypeBuilder, but we still need
// to deal with the case where the property's declaring
// type is one.
if (!(property.DeclaringType is TypeBuilder) ||
!con.DeclaringType.IsSubclassOf(((TypeBuilder)property.DeclaringType).BakedRuntimeType))
!con.DeclaringType.IsSubclassOf(((RuntimeTypeBuilder)property.DeclaringType).BakedRuntimeType))
throw new ArgumentException(SR.Argument_BadPropertyForConstructorBuilder);
}
}
Expand Down Expand Up @@ -204,14 +204,14 @@ public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs, Pr
// Might have failed check because one type is a XXXBuilder
// and the other is not. Deal with these special cases
// separately.
if (!TypeBuilder.IsTypeEqual(namedField.DeclaringType, con.DeclaringType))
if (!RuntimeTypeBuilder.IsTypeEqual(namedField.DeclaringType, con.DeclaringType))
{
// IsSubclassOf is overloaded to do the right thing if
// the constructor is a TypeBuilder, but we still need
// to deal with the case where the field's declaring
// type is one.
if (!(namedField.DeclaringType is TypeBuilder) ||
!con.DeclaringType.IsSubclassOf(((TypeBuilder)namedFields[i].DeclaringType!).BakedRuntimeType))
!con.DeclaringType.IsSubclassOf(((RuntimeTypeBuilder)namedFields[i].DeclaringType!).BakedRuntimeType))
throw new ArgumentException(SR.Argument_BadFieldForConstructorBuilder);
}
}
Expand Down Expand Up @@ -515,9 +515,9 @@ private static void EmitValue(BinaryWriter writer, Type type, object? value)
}

// return the byte interpretation of the custom attribute
internal void CreateCustomAttribute(ModuleBuilder mod, int tkOwner)
internal void CreateCustomAttribute(RuntimeModuleBuilder mod, int tkOwner)
{
TypeBuilder.DefineCustomAttribute(mod, tkOwner, mod.GetConstructorToken(m_con), m_blob);
RuntimeTypeBuilder.DefineCustomAttribute(mod, tkOwner, mod.GetConstructorToken(m_con), m_blob);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ private int GetMemberRefToken(MethodBase methodInfo, Type[]? optionalParameterTy
}

SignatureHelper sig = GetMethodSigHelper(methodInfo.CallingConvention,
MethodBuilder.GetMethodBaseReturnType(methodInfo),
RuntimeMethodBuilder.GetMethodBaseReturnType(methodInfo),
parameterTypes,
requiredCustomModifiers,
optionalCustomModifiers,
Expand Down
Loading