diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs index 3c2daf38b082f..fbc3136840f37 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs @@ -88,8 +88,8 @@ internal RuntimeMethodBuilder(string name, MethodAttributes attributes, CallingC } else if ((attributes & MethodAttributes.Virtual) != 0) { - // On an interface, the rule is slighlty different - if (((attributes & MethodAttributes.Abstract) == 0)) + // On an interface, the rule is slightly different + if ((attributes & MethodAttributes.Abstract) == 0) throw new ArgumentException(SR.Arg_NoStaticVirtual); } @@ -122,7 +122,7 @@ internal RuntimeMethodBuilder(string name, MethodAttributes attributes, CallingC m_ubBody = null; m_ilGenerator = null; - // Default is managed IL. Manged IL has bit flag 0x0020 set off + // Default is managed IL. Managed IL has bit flag 0x0020 set off m_dwMethodImplFlags = MethodImplAttributes.IL; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs index 38acdc04bb2f4..66733667c3af0 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs @@ -10,92 +10,6 @@ namespace System.Reflection.Emit { - public abstract partial class TypeBuilder - { - #region Public Static Methods - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "MakeGenericType is only called on a TypeBuilder which is not subject to trimming")] - public static MethodInfo GetMethod(Type type, MethodInfo method) - { - if (type is not TypeBuilder && type is not TypeBuilderInstantiation) - throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); - - // The following checks establishes invariants that more simply put require type to be generic and - // method to be a generic method definition declared on the generic type definition of type. - // To create generic method G.M these invariants require that G.M be created by calling - // this function followed by MakeGenericMethod on the resulting MethodInfo to finally get G.M. - // We could also allow G.M to be created before G.M (BindGenParm followed by this method) - // if we wanted to but that just complicates things so these checks are designed to prevent that scenario. - - if (method.IsGenericMethod && !method.IsGenericMethodDefinition) - throw new ArgumentException(SR.Argument_NeedGenericMethodDefinition, nameof(method)); - - if (method.DeclaringType == null || !method.DeclaringType.IsGenericTypeDefinition) - throw new ArgumentException(SR.Argument_MethodNeedGenericDeclaringType, nameof(method)); - - if (type.GetGenericTypeDefinition() != method.DeclaringType) - throw new ArgumentException(SR.Argument_InvalidMethodDeclaringType, nameof(type)); - - // The following converts from Type or TypeBuilder of G to TypeBuilderInstantiation G. These types - // both logically represent the same thing. The runtime displays a similar convention by having - // G.M() be encoded by a typeSpec whose parent is the typeDef for G and whose instantiation is also G. - if (type.IsGenericTypeDefinition) - type = type.MakeGenericType(type.GetGenericArguments()); - - if (type is not TypeBuilderInstantiation typeBuilderInstantiation) - throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type)); - - return MethodOnTypeBuilderInstantiation.GetMethod(method, typeBuilderInstantiation); - } - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "MakeGenericType is only called on a TypeBuilder which is not subject to trimming")] - public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor) - { - if (type is not TypeBuilder && type is not TypeBuilderInstantiation) - throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); - - if (!constructor.DeclaringType!.IsGenericTypeDefinition) - throw new ArgumentException(SR.Argument_ConstructorNeedGenericDeclaringType, nameof(constructor)); - - if (type.GetGenericTypeDefinition() != constructor.DeclaringType) - throw new ArgumentException(SR.Argument_InvalidConstructorDeclaringType, nameof(type)); - - // TypeBuilder G ==> TypeBuilderInstantiation G - if (type.IsGenericTypeDefinition) - type = type.MakeGenericType(type.GetGenericArguments()); - - if (type is not TypeBuilderInstantiation typeBuilderInstantiation) - throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type)); - - return ConstructorOnTypeBuilderInstantiation.GetConstructor(constructor, typeBuilderInstantiation); - } - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "MakeGenericType is only called on a TypeBuilder which is not subject to trimming")] - public static FieldInfo GetField(Type type, FieldInfo field) - { - if (type is not TypeBuilder and not TypeBuilderInstantiation) - throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); - - if (!field.DeclaringType!.IsGenericTypeDefinition) - throw new ArgumentException(SR.Argument_FieldNeedGenericDeclaringType, nameof(field)); - - if (type.GetGenericTypeDefinition() != field.DeclaringType) - throw new ArgumentException(SR.Argument_InvalidFieldDeclaringType, nameof(type)); - - // TypeBuilder G ==> TypeBuilderInstantiation G - if (type.IsGenericTypeDefinition) - type = type.MakeGenericType(type.GetGenericArguments()); - - if (type is not TypeBuilderInstantiation typeBuilderInstantiation) - throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type)); - - return FieldOnTypeBuilderInstantiation.GetField(field, typeBuilderInstantiation); - } - #endregion - } - internal sealed partial class RuntimeTypeBuilder : TypeBuilder { public override bool IsAssignableFrom([NotNullWhen(true)] TypeInfo? typeInfo) @@ -1358,7 +1272,6 @@ private RuntimeConstructorBuilder DefineDefaultConstructorNoLock(MethodAttribute // Define the constructor Builder constBuilder = (RuntimeConstructorBuilder)DefineConstructor(attributes, CallingConventions.Standard, null); - m_constructorCount++; // generate the code to call the parent's default constructor ILGenerator il = constBuilder.GetILGenerator(); diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 5e65109ddbb37..c916e0ad2cc95 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -668,13 +668,13 @@ - + - + @@ -682,7 +682,7 @@ - + @@ -2737,4 +2737,4 @@ - + \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorOnTypeBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorOnTypeBuilderInstantiation.cs index 98ef5f8cccedc..c4e80153cf1a3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorOnTypeBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/ConstructorOnTypeBuilderInstantiation.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Globalization; namespace System.Reflection.Emit @@ -9,9 +8,9 @@ namespace System.Reflection.Emit internal sealed partial class ConstructorOnTypeBuilderInstantiation : ConstructorInfo { #region Private Static Members - internal static ConstructorInfo GetConstructor(ConstructorInfo Constructor, TypeBuilderInstantiation type) + internal static ConstructorInfo GetConstructor(ConstructorInfo constructor, TypeBuilderInstantiation type) { - return new ConstructorOnTypeBuilderInstantiation(Constructor, type); + return new ConstructorOnTypeBuilderInstantiation(constructor, type); } #endregion @@ -23,8 +22,6 @@ internal static ConstructorInfo GetConstructor(ConstructorInfo Constructor, Type #region Constructor internal ConstructorOnTypeBuilderInstantiation(ConstructorInfo constructor, TypeBuilderInstantiation type) { - Debug.Assert(constructor is ConstructorBuilder || constructor is RuntimeConstructorInfo); - _ctor = constructor; _type = type; } @@ -45,23 +42,7 @@ internal override Type[] GetParameterTypes() public override object[] GetCustomAttributes(bool inherit) { return _ctor.GetCustomAttributes(inherit); } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { return _ctor.GetCustomAttributes(attributeType, inherit); } public override bool IsDefined(Type attributeType, bool inherit) { return _ctor.IsDefined(attributeType, inherit); } - public override int MetadataToken - { - get - { - ConstructorBuilder? cb = _ctor as ConstructorBuilder; - - if (cb != null) - { - return cb.MetadataToken; - } - else - { - Debug.Assert(_ctor is RuntimeConstructorInfo); - return _ctor.MetadataToken; - } - } - } + public override int MetadataToken => _ctor.MetadataToken; public override Module Module => _ctor.Module; #endregion diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs index 1aadda2346a01..006795ce3692e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Globalization; namespace System.Reflection.Emit @@ -35,8 +34,6 @@ internal static FieldInfo GetField(FieldInfo Field, TypeBuilderInstantiation typ #region Constructor internal FieldOnTypeBuilderInstantiation(FieldInfo field, TypeBuilderInstantiation type) { - Debug.Assert(field is FieldBuilder || field is RuntimeFieldInfo); - _field = field; _type = type; } @@ -52,23 +49,7 @@ internal FieldOnTypeBuilderInstantiation(FieldInfo field, TypeBuilderInstantiati public override object[] GetCustomAttributes(bool inherit) { return _field.GetCustomAttributes(inherit); } public override object[] GetCustomAttributes(Type attributeType, bool inherit) { return _field.GetCustomAttributes(attributeType, inherit); } public override bool IsDefined(Type attributeType, bool inherit) { return _field.IsDefined(attributeType, inherit); } - public override int MetadataToken - { - get - { - FieldBuilder? fb = _field as FieldBuilder; - - if (fb != null) - { - return fb.MetadataToken; - } - else - { - Debug.Assert(_field is RuntimeFieldInfo); - return _field.MetadataToken; - } - } - } + public override int MetadataToken => _field.MetadataToken; public override Module Module => _field.Module; #endregion @@ -84,7 +65,7 @@ public override object GetValueDirect(TypedReference obj) throw new NotImplementedException(); } public override RuntimeFieldHandle FieldHandle => throw new NotImplementedException(); - public override Type FieldType => throw new NotImplementedException(); + public override Type FieldType => _field.FieldType; public override object GetValue(object? obj) { throw new InvalidOperationException(); } public override void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, CultureInfo? culture) { throw new InvalidOperationException(); } public override FieldAttributes Attributes => _field.Attributes; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs index 5ffd4b6747ef5..6c0867dbe3158 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilderInstantiation.cs @@ -32,10 +32,12 @@ internal MethodBuilderInstantiation(MethodInfo method, Type[] inst) } #endregion +#if SYSTEM_PRIVATE_CORELIB internal override Type[] GetParameterTypes() { return _method.GetParameterTypes(); } +#endif #region MemberBase public override MemberTypes MemberType => _method.MemberType; @@ -49,7 +51,7 @@ internal override Type[] GetParameterTypes() #endregion #region MethodBase Members - public override ParameterInfo[] GetParameters() { throw new NotSupportedException(); } + public override ParameterInfo[] GetParameters() => _method.GetParameters(); public override MethodImplAttributes GetMethodImplementationFlags() { return _method.GetMethodImplementationFlags(); } public override RuntimeMethodHandle MethodHandle => throw new NotSupportedException(SR.NotSupported_DynamicModule); public override MethodAttributes Attributes => _method.Attributes; @@ -82,6 +84,7 @@ public override bool ContainsGenericParameters } } + [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")] [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] public override MethodInfo MakeGenericMethod(params Type[] arguments) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs index 02c34feac5b29..1afed496f67be 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/MethodOnTypeBuilderInstantiation.cs @@ -1,7 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; @@ -24,8 +23,6 @@ internal static MethodInfo GetMethod(MethodInfo method, TypeBuilderInstantiation #region Constructor internal MethodOnTypeBuilderInstantiation(MethodInfo method, Type type) { - Debug.Assert(method is MethodBuilder || method is RuntimeMethodInfo); - _method = method; _type = type; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs index 8d3f6e76caf0f..ecf9a39418232 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs @@ -286,7 +286,7 @@ public override Type MakeArrayType(int rank) public override int GetArrayRank() { if (!IsArray) - throw new NotSupportedException(SR.NotSupported_SubclassOverride); + throw new ArgumentException(SR.Argument_HasToBeArrayClass); return _rank; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs index d6b09419bd8fb..1ae9e44c88cac 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilder.cs @@ -6,7 +6,7 @@ namespace System.Reflection.Emit { - public abstract partial class TypeBuilder : TypeInfo + public abstract class TypeBuilder : TypeInfo { protected TypeBuilder() { @@ -320,5 +320,120 @@ public override Type MakeGenericType(params Type[] typeArguments) { return TypeBuilderInstantiation.MakeGenericType(this, typeArguments); } + + #region Public Static Methods + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", + Justification = "MakeGenericType is only called on a TypeBuilder which is not subject to trimming")] + public static MethodInfo GetMethod(Type type, MethodInfo method) + { + if (type is not TypeBuilder && type is not TypeBuilderInstantiation) + { + throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); + } + + // The following checks establishes invariants that more simply put require type to be generic and + // method to be a generic method definition declared on the generic type definition of type. + // To create generic method G.M these invariants require that G.M be created by calling + // this function followed by MakeGenericMethod on the resulting MethodInfo to finally get G.M. + // We could also allow G.M to be created before G.M (BindGenParm followed by this method) + // if we wanted to but that just complicates things so these checks are designed to prevent that scenario. + + if (method.IsGenericMethod && !method.IsGenericMethodDefinition) + { + throw new ArgumentException(SR.Argument_NeedGenericMethodDefinition, nameof(method)); + } + + if (method.DeclaringType == null || !method.DeclaringType.IsGenericTypeDefinition) + { + throw new ArgumentException(SR.Argument_MethodNeedGenericDeclaringType, nameof(method)); + } + + if (type.GetGenericTypeDefinition() != method.DeclaringType) + { + throw new ArgumentException(SR.Argument_InvalidMethodDeclaringType, nameof(type)); + } + + // The following converts from Type or TypeBuilder of G to TypeBuilderInstantiation G. These types + // both logically represent the same thing. The runtime displays a similar convention by having + // G.M() be encoded by a typeSpec whose parent is the typeDef for G and whose instantiation is also G. + if (type.IsGenericTypeDefinition) + { + type = type.MakeGenericType(type.GetGenericArguments()); + } + + if (type is not TypeBuilderInstantiation typeBuilderInstantiation) + { + throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type)); + } + + return MethodOnTypeBuilderInstantiation.GetMethod(method, typeBuilderInstantiation); + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", + Justification = "MakeGenericType is only called on a TypeBuilder which is not subject to trimming")] + public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor) + { + if (type is not TypeBuilder && type is not TypeBuilderInstantiation) + { + throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); + } + + if (!constructor.DeclaringType!.IsGenericTypeDefinition) + { + throw new ArgumentException(SR.Argument_ConstructorNeedGenericDeclaringType, nameof(constructor)); + } + + if (type.GetGenericTypeDefinition() != constructor.DeclaringType) + { + throw new ArgumentException(SR.Argument_InvalidConstructorDeclaringType, nameof(type)); + } + + // TypeBuilder G ==> TypeBuilderInstantiation G + if (type.IsGenericTypeDefinition) + { + type = type.MakeGenericType(type.GetGenericArguments()); + } + + if (type is not TypeBuilderInstantiation typeBuilderInstantiation) + { + throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type)); + } + + return ConstructorOnTypeBuilderInstantiation.GetConstructor(constructor, typeBuilderInstantiation); + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", + Justification = "MakeGenericType is only called on a TypeBuilder which is not subject to trimming")] + public static FieldInfo GetField(Type type, FieldInfo field) + { + if (type is not TypeBuilder and not TypeBuilderInstantiation) + { + throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); + } + + if (!field.DeclaringType!.IsGenericTypeDefinition) + { + throw new ArgumentException(SR.Argument_FieldNeedGenericDeclaringType, nameof(field)); + } + + if (type.GetGenericTypeDefinition() != field.DeclaringType) + { + throw new ArgumentException(SR.Argument_InvalidFieldDeclaringType, nameof(type)); + } + + // TypeBuilder G ==> TypeBuilderInstantiation G + if (type.IsGenericTypeDefinition) + { + type = type.MakeGenericType(type.GetGenericArguments()); + } + + if (type is not TypeBuilderInstantiation typeBuilderInstantiation) + { + throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type)); + } + + return FieldOnTypeBuilderInstantiation.GetField(field, typeBuilderInstantiation); + } + #endregion } } diff --git a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx index 2eb955c372310..6572d94d71d67 100644 --- a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx @@ -186,6 +186,9 @@ Method body should not exist. + + Interface cannot have constructors. + Local passed in does not belong to this ILGenerator. @@ -198,6 +201,21 @@ The specified opcode cannot be passed to EmitCall. + + Unable to access ILGenerator on a constructor created with DefineDefaultConstructor. + + + Parent does not have a default constructor. The default constructor must be explicitly defined. + + + Unable to change after type has been created. + + + The invoked member is not supported before the type is created. + + + Method cannot be both static and virtual. + Incorrect code generation for exception block. @@ -207,4 +225,7 @@ Should not specify exception type for catch clause for filter block. + + {0} is not a GenericMethodDefinition. MakeGenericMethod may only be called on a method for which MethodBase.IsGenericMethodDefinition is true. + \ No newline at end of file diff --git a/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj b/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj index 988022d355b2a..ede82acce0a97 100644 --- a/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj +++ b/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj @@ -8,7 +8,9 @@ + + diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs index 5a74358e6f318..2048b14fff0f1 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/AssemblyBuilderImpl.cs @@ -114,7 +114,7 @@ protected override ModuleBuilder DefineDynamicModuleCore(string name) throw new InvalidOperationException(SR.InvalidOperation_NoMultiModuleAssembly); } - _module = new ModuleBuilderImpl(name, _coreAssembly, _metadataBuilder); + _module = new ModuleBuilderImpl(name, _coreAssembly, _metadataBuilder, this); return _module; } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ConstructorBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ConstructorBuilderImpl.cs new file mode 100644 index 0000000000000..9fca44c0a608a --- /dev/null +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ConstructorBuilderImpl.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Globalization; + +namespace System.Reflection.Emit +{ + internal sealed class ConstructorBuilderImpl : ConstructorBuilder + { + internal readonly MethodBuilderImpl _methodBuilder; + internal bool _isDefaultConstructor; + + public ConstructorBuilderImpl(string name, MethodAttributes attributes, CallingConventions callingConvention, + Type[]? parameterTypes, ModuleBuilderImpl mod, TypeBuilderImpl type) + { + _methodBuilder = new MethodBuilderImpl(name, attributes, callingConvention, null, parameterTypes, mod, type); + + type._methodDefinitions.Add(_methodBuilder); + } + + protected override bool InitLocalsCore + { + get => _methodBuilder.InitLocals; + set => _methodBuilder.InitLocals = value; + } + + protected override ParameterBuilder DefineParameterCore(int iSequence, ParameterAttributes attributes, string strParamName) => + _methodBuilder.DefineParameter(iSequence, attributes, strParamName); + + protected override ILGenerator GetILGeneratorCore(int streamSize) + { + if (_isDefaultConstructor) + { + throw new InvalidOperationException(SR.InvalidOperation_DefaultConstructorILGen); + } + + return _methodBuilder.GetILGenerator(streamSize); + } + + protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan binaryAttribute) => + _methodBuilder.SetCustomAttribute(con, binaryAttribute); + + protected override void SetImplementationFlagsCore(MethodImplAttributes attributes) => + _methodBuilder.SetImplementationFlags(attributes); + + public override string Name => _methodBuilder.Name; + + public override MethodAttributes Attributes => _methodBuilder.Attributes; + + public override CallingConventions CallingConvention + { + get + { + if (DeclaringType!.IsGenericType) + { + return CallingConventions.HasThis; + } + + return CallingConventions.Standard; + } + } + + public override TypeBuilder DeclaringType => _methodBuilder.DeclaringType; + + public override Module Module => _methodBuilder.Module; + + public override int MetadataToken => _methodBuilder.MetadataToken; + + public override Type? ReflectedType => _methodBuilder.ReflectedType; + + public override MethodImplAttributes GetMethodImplementationFlags() => _methodBuilder.GetMethodImplementationFlags(); + + public override RuntimeMethodHandle MethodHandle => throw new NotSupportedException(SR.NotSupported_DynamicModule); + public override object[] GetCustomAttributes(bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule); + public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule); + public override ParameterInfo[] GetParameters() => _methodBuilder.GetParameters(); + public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) + => throw new NotSupportedException(SR.NotSupported_DynamicModule); + public override object Invoke(BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) => + throw new NotSupportedException(SR.NotSupported_DynamicModule); + public override bool IsDefined(Type attributeType, bool inherit) => throw new NotSupportedException(SR.NotSupported_DynamicModule); + } +} diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/EnumBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/EnumBuilderImpl.cs index b11a3cb2989d1..edb95e889846f 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/EnumBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/EnumBuilderImpl.cs @@ -11,12 +11,13 @@ internal sealed class EnumBuilderImpl : EnumBuilder private readonly FieldBuilder _underlyingField; internal readonly TypeBuilderImpl _typeBuilder; - internal EnumBuilderImpl(string name, Type underlyingType, TypeAttributes visibility, ModuleBuilderImpl module, TypeDefinitionHandle typeHandle) + internal EnumBuilderImpl(string name, Type underlyingType, TypeAttributes visibility, ModuleBuilderImpl module) { if ((visibility & ~TypeAttributes.VisibilityMask) != 0) throw new ArgumentException(SR.Argument_ShouldOnlySetVisibilityFlags, nameof(name)); - _typeBuilder = new TypeBuilderImpl(name, visibility | TypeAttributes.Sealed, typeof(Enum), module, typeHandle, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize, null); + _typeBuilder = new TypeBuilderImpl(name, visibility | TypeAttributes.Sealed, typeof(Enum), module, + interfaces: null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize, enclosingType: null); // Define the underlying field for the enum. It will be a non-static, private field with special name bit set. _underlyingField = _typeBuilder.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs index fbaa3af6452ff..7fa928d22b689 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/GenericTypeParameterBuilderImpl.cs @@ -22,12 +22,11 @@ internal sealed class GenericTypeParameterBuilderImpl : GenericTypeParameterBuil private MethodBuilderImpl? _methodBuilder; internal EntityHandle _parentHandle; - internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder, EntityHandle parentHandle) + internal GenericTypeParameterBuilderImpl(string name, int genParamPosition, TypeBuilderImpl typeBuilder) { _name = name; _genParamPosition = genParamPosition; _type = typeBuilder; - _parentHandle = parentHandle; } public GenericTypeParameterBuilderImpl(string name, int genParamPosition, MethodBuilderImpl methodBuilder) @@ -85,7 +84,7 @@ public override Type[] GetGenericParameterConstraints() => public override bool IsGenericParameter => true; public override bool IsConstructedGenericType => false; public override bool ContainsGenericParameters => _type.ContainsGenericParameters; - public override MethodBase? DeclaringMethod => throw new NotImplementedException(); + public override MethodBase? DeclaringMethod => _type.DeclaringMethod; public override Type? BaseType => _parent; public override RuntimeTypeHandle TypeHandle => throw new NotSupportedException(); public override Guid GUID => throw new NotSupportedException(); diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs index 123846778fed3..8810a1819df38 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ILGeneratorImpl.cs @@ -369,7 +369,14 @@ public override void Emit(OpCode opcode, ConstructorInfo con) // Push the return value stackChange++; // Pop the parameters. - stackChange -= con.GetParameters().Length; + if (con is ConstructorBuilderImpl builder) + { + stackChange -= builder._methodBuilder.ParameterCount; + } + else + { + stackChange -= con.GetParameters().Length; + } // Pop the this parameter if the constructor is non-static and the // instruction is not newobj. if (!con.IsStatic && !opcode.Equals(OpCodes.Newobj)) diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs index afb6518fe261c..0ff656d3b290d 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/MethodBuilderImpl.cs @@ -13,7 +13,7 @@ namespace System.Reflection.Emit internal sealed class MethodBuilderImpl : MethodBuilder { private Type _returnType; - private Type[]? _parameterTypes; + internal Type[]? _parameterTypes; private readonly ModuleBuilderImpl _module; private readonly string _name; private readonly CallingConventions _callingConventions; @@ -26,7 +26,7 @@ internal sealed class MethodBuilderImpl : MethodBuilder internal DllImportData? _dllImportData; internal List? _customAttributes; - internal ParameterBuilderImpl[]? _parameters; + internal ParameterBuilderImpl[]? _parameterBuilders; internal MethodDefinitionHandle _handle; internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConventions callingConventions, Type? returnType, @@ -36,13 +36,24 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv _returnType = returnType ?? _module.GetTypeFromCoreAssembly(CoreTypeId.Void); _name = name; _attributes = attributes; + + if ((attributes & MethodAttributes.Static) == 0) + { + // turn on the has this calling convention + callingConventions |= CallingConventions.HasThis; + } + else if ((attributes & (MethodAttributes.Virtual | MethodAttributes.Abstract)) == MethodAttributes.Virtual) + { + throw new ArgumentException(SR.Argument_NoStaticVirtual); + } + _callingConventions = callingConventions; _declaringType = declaringType; if (parameterTypes != null) { _parameterTypes = new Type[parameterTypes.Length]; - _parameters = new ParameterBuilderImpl[parameterTypes.Length + 1]; // parameter 0 reserved for return type + _parameterBuilders = new ParameterBuilderImpl[parameterTypes.Length + 1]; // parameter 0 reserved for return type for (int i = 0; i < parameterTypes.Length; i++) { ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes)); @@ -53,7 +64,9 @@ internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConv _initLocals = true; } - internal int ParameterCount => _parameterTypes == null? 0 : _parameterTypes.Length; + internal int ParameterCount => _parameterTypes == null ? 0 : _parameterTypes.Length; + + internal Type[]? ParameterTypes => _parameterTypes; internal ILGeneratorImpl? ILGeneratorImpl => _ilGenerator; @@ -77,6 +90,16 @@ internal static SignatureCallingConvention GetSignatureConvention(CallingConvent return convention; } + + internal BindingFlags GetBindingFlags() + { + BindingFlags bindingFlags = (_attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.Public ? + BindingFlags.Public : BindingFlags.NonPublic; + bindingFlags |= (_attributes & MethodAttributes.Static) != 0 ? BindingFlags.Static : BindingFlags.Instance; + + return bindingFlags; + } + protected override bool InitLocalsCore { get { ThrowIfGeneric(); return _initLocals; } @@ -103,14 +126,18 @@ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(par protected override ParameterBuilder DefineParameterCore(int position, ParameterAttributes attributes, string? strParamName) { + _declaringType.ThrowIfCreated(); + if (position > 0 && (_parameterTypes == null || position > _parameterTypes.Length)) + { throw new ArgumentOutOfRangeException(SR.ArgumentOutOfRange_ParamSequence); + } - _parameters ??= new ParameterBuilderImpl[1]; + _parameterBuilders ??= new ParameterBuilderImpl[1]; attributes &= ~ParameterAttributes.ReservedMask; ParameterBuilderImpl parameter = new ParameterBuilderImpl(this, position, attributes, strParamName); - _parameters[position] = parameter; + _parameterBuilders[position] = parameter; return parameter; } @@ -136,6 +163,9 @@ protected override ILGenerator GetILGeneratorCore(int size) return _ilGenerator ??= new ILGeneratorImpl(this, size); } + internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan binaryAttribute) => + SetCustomAttributeCore(con, binaryAttribute); + protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan binaryAttribute) { // Handle pseudo custom attributes @@ -172,8 +202,10 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan protected override void SetImplementationFlagsCore(MethodImplAttributes attributes) { + _declaringType.ThrowIfCreated(); _methodImplFlags = attributes; } + protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) { @@ -185,7 +217,7 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq if (parameterTypes != null) { _parameterTypes = new Type[parameterTypes.Length]; - _parameters = new ParameterBuilderImpl[parameterTypes.Length + 1]; // parameter 0 reserved for return type + _parameterBuilders = new ParameterBuilderImpl[parameterTypes.Length + 1]; // parameter 0 reserved for return type for (int i = 0; i < parameterTypes.Length; i++) { ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes)); @@ -193,6 +225,7 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq } // TODO: Add support for other parameters: returnTypeRequiredCustomModifiers, returnTypeOptionalCustomModifiers, parameterTypeRequiredCustomModifiers and parameterTypeOptionalCustomModifiers } + public override string Name => _name; public override MethodAttributes Attributes => _attributes; public override CallingConventions CallingConvention => _callingConventions; @@ -206,7 +239,7 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq public override bool IsSecurityTransparent => false; public override int MetadataToken => _handle == default ? 0 : MetadataTokens.GetToken(_handle); public override RuntimeMethodHandle MethodHandle => throw new NotSupportedException(SR.NotSupported_DynamicModule); - public override Type? ReflectedType { get => throw new NotImplementedException(); } + public override Type? ReflectedType => _declaringType; public override ParameterInfo ReturnParameter { get => throw new NotImplementedException(); } public override Type ReturnType => _returnType; public override ICustomAttributeProvider ReturnTypeCustomAttributes { get => throw new NotImplementedException(); } @@ -221,13 +254,37 @@ protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeReq public override MethodInfo GetGenericMethodDefinition() => !IsGenericMethod ? throw new InvalidOperationException() : this; - public override int GetHashCode() - => throw new NotImplementedException(); - public override MethodImplAttributes GetMethodImplementationFlags() => _methodImplFlags; - public override ParameterInfo[] GetParameters() => throw new NotImplementedException(); + public override ParameterInfo[] GetParameters() + { + // This is called from ILGenerator when Emit(OpCode, ConstructorInfo) when the ctor is + // instance of 'ConstructorOnTypeBuilderInstantiation', so we could not throw here even + // the type was not baked. Runtime implementation throws when the type is not baked. + + if (_parameterTypes == null) + { + return Array.Empty(); + } + + _parameterBuilders ??= new ParameterBuilderImpl[_parameterTypes.Length + 1]; // parameter 0 reserved for return type + ParameterInfo[] parameters = new ParameterInfo[_parameterTypes.Length]; + + for (int i = 0; i < _parameterTypes.Length; i++) + { + if (_parameterBuilders[i + 1] == null) + { + parameters[i] = new ParameterInfoWrapper(new ParameterBuilderImpl(this, i, ParameterAttributes.None, null), _parameterTypes[i]); + } + else + { + parameters[i] = new ParameterInfoWrapper(_parameterBuilders[i + 1], _parameterTypes[i]); + } + } + + return parameters; + } public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture) => throw new NotSupportedException(SR.NotSupported_DynamicModule); @@ -236,7 +293,7 @@ public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? bind [RequiresDynamicCode("The native code for this instantiation might not be available at runtime.")] [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] - public override MethodInfo MakeGenericMethod(params Type[] typeArguments) - => throw new NotImplementedException(); + public override MethodInfo MakeGenericMethod(params Type[] typeArguments) => + MethodBuilderInstantiation.MakeGenericMethod(this, typeArguments); } } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs index 855fdb5591233..68d839986bd32 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ModuleBuilderImpl.cs @@ -15,9 +15,10 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder private readonly Assembly _coreAssembly; private readonly string _name; private readonly MetadataBuilder _metadataBuilder; + private readonly AssemblyBuilderImpl _assemblyBuilder; private readonly Dictionary _assemblyReferences = new(); - private readonly Dictionary _typeReferences = new(); - private readonly Dictionary _memberReferences = new(); + private readonly Dictionary _typeReferences = new(); + private readonly Dictionary _memberReferences = new(); private readonly List _typeDefinitions = new(); private readonly Dictionary _ctorReferences = new(); private Dictionary? _moduleReferences; @@ -31,11 +32,12 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder 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) }; - internal ModuleBuilderImpl(string name, Assembly coreAssembly, MetadataBuilder builder) + internal ModuleBuilderImpl(string name, Assembly coreAssembly, MetadataBuilder builder, AssemblyBuilderImpl assemblyBuilder) { _coreAssembly = coreAssembly; _name = name; _metadataBuilder = builder; + _assemblyBuilder = assemblyBuilder; } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Types are preserved via s_coreTypes")] @@ -120,13 +122,15 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder) WriteCustomAttributes(_customAttributes, moduleHandle); - PrePopulateTypeMembersTokens(); + _typeDefinitions.Sort((x, y) => x.MetadataToken.CompareTo(y.MetadataToken)); // All generic parameters for all types and methods should be written in specific order List genericParams = new(); // Add each type definition to metadata table. foreach (TypeBuilderImpl typeBuilder in _typeDefinitions) { + typeBuilder.ThrowIfNotCreated(); + EntityHandle parent = default; if (typeBuilder.BaseType is not null) { @@ -140,6 +144,7 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder) { foreach (GenericTypeParameterBuilderImpl param in typeBuilder.GenericTypeParameters) { + param._parentHandle = typeHandle; genericParams.Add(param); } } @@ -183,19 +188,7 @@ internal void AppendMetadata(MethodBodyStreamEncoder methodBodyEncoder) } } - // Need to pre populate all type members tokens so that they can be referenced from other type's metadata - private void PrePopulateTypeMembersTokens() - { - foreach (TypeBuilderImpl typeBuilder in _typeDefinitions) - { - typeBuilder._firsMethodToken = _nextMethodDefRowId; - typeBuilder._firstFieldToken = _nextFieldDefRowId; - PrePopulateMethodDefinitionHandles(typeBuilder._methodDefinitions); - PrePopulateFieldDefinitionHandles(typeBuilder._fieldDefinitions); - } - } - - private void PrePopulateFieldDefinitionHandles(List fieldDefinitions) + private void PopulateFieldDefinitionHandles(List fieldDefinitions) { foreach (FieldBuilderImpl field in fieldDefinitions) { @@ -203,7 +196,7 @@ private void PrePopulateFieldDefinitionHandles(List fieldDefin } } - private void PrePopulateMethodDefinitionHandles(List methods) + private void PopulateMethodDefinitionHandles(List methods) { foreach (MethodBuilderImpl method in methods) { @@ -211,6 +204,15 @@ private void PrePopulateMethodDefinitionHandles(List methods) } } + internal void PopulateTypeAndItsMembersTokens(TypeBuilderImpl typeBuilder) + { + typeBuilder._handle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId); + typeBuilder._firsMethodToken = _nextMethodDefRowId; + typeBuilder._firstFieldToken = _nextFieldDefRowId; + PopulateMethodDefinitionHandles(typeBuilder._methodDefinitions); + PopulateFieldDefinitionHandles(typeBuilder._fieldDefinitions); + } + private void WriteMethods(List methods, List genericParams, MethodBodyStreamEncoder methodBodyEncoder) { foreach (MethodBuilderImpl method in methods) @@ -240,9 +242,9 @@ private void WriteMethods(List methods, List methods, List pair in il.GetMemberReferences()) @@ -340,7 +343,7 @@ private MemberReferenceHandle GetConstructorHandle(ConstructorInfo constructorIn { if (!_ctorReferences.TryGetValue(constructorInfo, out var constructorHandle)) { - TypeReferenceHandle parentHandle = GetTypeReference(constructorInfo.DeclaringType!); + EntityHandle parentHandle = GetTypeReferenceOrSpecificationHandle(constructorInfo.DeclaringType!); constructorHandle = AddConstructorReference(parentHandle, constructorInfo); _ctorReferences.Add(constructorInfo, constructorHandle); } @@ -348,22 +351,47 @@ private MemberReferenceHandle GetConstructorHandle(ConstructorInfo constructorIn return constructorHandle; } - private TypeReferenceHandle GetTypeReference(Type type) + private EntityHandle GetTypeReferenceOrSpecificationHandle(Type type) { if (!_typeReferences.TryGetValue(type, out var typeHandle)) { - typeHandle = AddTypeReference(type, GetAssemblyReference(type.Assembly)); + if (type.IsArray || type.IsGenericParameter || (type.IsGenericType && !type.IsGenericTypeDefinition)) + { + typeHandle = AddTypeSpecification(type); + } + else + { + typeHandle = AddTypeReference(type, GetAssemblyReference(type.Assembly)); + } + _typeReferences.Add(type, typeHandle); } return typeHandle; } - private MemberReferenceHandle GetMemberReference(MemberInfo member) + 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))); + + private EntityHandle GetMemberReference(MemberInfo member) { if (!_memberReferences.TryGetValue(member, out var memberHandle)) { - memberHandle = AddMemberReference(member.Name, GetTypeReference(member.DeclaringType!), GetMemberSignature(member)); + if (member is MethodInfo method && method.IsConstructedGenericMethod) + { + memberHandle = AddMethodSpecification(GetMemberReference(method.GetGenericMethodDefinition()), method.GetGenericArguments()); + } + else + { + memberHandle = AddMemberReference(member.Name, GetTypeHandle(member.DeclaringType!), GetMemberSignature(member)); + } + _memberReferences.Add(member, memberHandle); } @@ -474,7 +502,7 @@ private MemberReferenceHandle AddMemberReference(string memberName, EntityHandle name: _metadataBuilder.GetOrAddString(memberName), signature: _metadataBuilder.GetOrAddBlob(signature)); - private MemberReferenceHandle AddConstructorReference(TypeReferenceHandle parent, ConstructorInfo method) + private MemberReferenceHandle AddConstructorReference(EntityHandle parent, ConstructorInfo method) { var blob = MetadataSignatureHelper.ConstructorSignatureEncoder(method.GetParameters(), this); return _metadataBuilder.AddMemberReference( @@ -528,7 +556,7 @@ internal EntityHandle GetTypeHandle(Type type) return eb._typeBuilder._handle; } - return GetTypeReference(type); + return GetTypeReferenceOrSpecificationHandle(type); } internal EntityHandle GetMemberHandle(MemberInfo member) @@ -543,14 +571,18 @@ internal EntityHandle GetMemberHandle(MemberInfo member) return fb._handle; } + if (member is ConstructorBuilderImpl ctor && Equals(ctor.Module)) + { + return ctor._methodBuilder._handle; + } + return GetMemberReference(member); } internal TypeBuilder DefineNestedType(string name, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize, TypeBuilderImpl? enclosingType) { - TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId); - TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle, interfaces, packingSize, typesize, enclosingType); + TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, interfaces, packingSize, typesize, enclosingType); _typeDefinitions.Add(_type); return _type; } @@ -558,6 +590,7 @@ internal TypeBuilder DefineNestedType(string name, TypeAttributes attr, [Dynamic [RequiresAssemblyFiles("Returns for modules with no file path")] public override string Name => ""; public override string ScopeName => _name; + public override Assembly Assembly => _assemblyBuilder; public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException(); public override int GetFieldMetadataToken(FieldInfo field) @@ -590,8 +623,7 @@ public override int GetMethodMetadataToken(MethodInfo method) protected override EnumBuilder DefineEnumCore(string name, TypeAttributes visibility, Type underlyingType) { - TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId); - EnumBuilderImpl enumBuilder = new EnumBuilderImpl(name, underlyingType, visibility, this, typeHandle); + EnumBuilderImpl enumBuilder = new EnumBuilderImpl(name, underlyingType, visibility, this); _typeDefinitions.Add(enumBuilder._typeBuilder); return enumBuilder; } @@ -603,8 +635,7 @@ protected override EnumBuilder DefineEnumCore(string name, TypeAttributes visibi protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize) { - TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId); - TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle, interfaces, packingSize, typesize, null); + TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, interfaces, packingSize, typesize, null); _typeDefinitions.Add(_type); return _type; } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs index 4d64a644ab47e..f5b165b62cba8 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/ParameterBuilderImpl.cs @@ -9,8 +9,8 @@ internal sealed class ParameterBuilderImpl : ParameterBuilder { private readonly string? _name; private readonly int _position; - private readonly MethodBuilderImpl _methodBuilder; - private ParameterAttributes _attributes; + internal readonly MethodBuilderImpl _methodBuilder; + internal ParameterAttributes _attributes; internal List? _customAttributes; internal MarshallingData? _marshallingData; @@ -60,4 +60,28 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan _customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute)); } } + + internal sealed class ParameterInfoWrapper : ParameterInfo + { + private readonly ParameterBuilderImpl _pb; + private readonly Type _type +; + public ParameterInfoWrapper(ParameterBuilderImpl pb, Type type) + { + _pb = pb; + _type = type; + } + + public override ParameterAttributes Attributes => _pb._attributes; + + public override string? Name => _pb.Name; + + public override int Position => _pb.Position; + + public override Type ParameterType => _type; + + public override bool HasDefaultValue => _pb._defaultValue != DBNull.Value; + + public override object? DefaultValue => HasDefaultValue ? _pb._defaultValue : null; + } } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs index 8a165f306fbe9..c84052be93741 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/SignatureHelper.cs @@ -56,6 +56,27 @@ internal static BlobBuilder ConstructorSignatureEncoder(ParameterInfo[]? paramet return constructorSignature; } + internal static BlobBuilder GetTypeSpecificationSignature(Type type, ModuleBuilderImpl module) + { + BlobBuilder typeSpecSignature = new(); + WriteSignatureForType(new BlobEncoder(typeSpecSignature).TypeSpecificationSignature(), type, module); + + return typeSpecSignature; + } + + internal static BlobBuilder GetMethodSpecificationSignature(Type[] genericArguments, ModuleBuilderImpl module) + { + BlobBuilder methodSpecSignature = new(); + GenericTypeArgumentsEncoder encoder = new BlobEncoder(methodSpecSignature).MethodSpecificationSignature(genericArguments.Length); + + foreach (Type argument in genericArguments) + { + WriteSignatureForType(encoder.AddArgument(), argument, module); + } + + return methodSpecSignature; + } + internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Type[]? parameters, Type? returnType, SignatureCallingConvention convention, int genParamCount, bool isInstance) { diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs index eb7f7dd8814dd..cd81dc793baa4 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeBuilderImpl.cs @@ -24,18 +24,20 @@ internal sealed class TypeBuilderImpl : TypeBuilder private PackingSize _packingSize; private int _typeSize; private Type? _enumUnderlyingType; + private bool _isCreated; - internal readonly TypeDefinitionHandle _handle; + internal TypeDefinitionHandle _handle; internal int _firstFieldToken; internal int _firsMethodToken; internal readonly List _methodDefinitions = new(); internal readonly List _fieldDefinitions = new(); + internal readonly List _constructorDefinitions = new(); internal List? _interfaces; internal List? _customAttributes; internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, ModuleBuilderImpl module, - TypeDefinitionHandle handle, Type[]? interfaces, PackingSize packingSize, int typeSize, TypeBuilderImpl? enclosingType) + Type[]? interfaces, PackingSize packingSize, int typeSize, TypeBuilderImpl? enclosingType) { _name = fullName; _module = module; @@ -43,7 +45,6 @@ internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes, _packingSize = packingSize; _typeSize = typeSize; SetParent(parent); - _handle = handle; _declaringType = enclosingType; // Extract namespace from fullName @@ -73,19 +74,115 @@ internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes, protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes.All))] Type interfaceType) { + ThrowIfCreated(); + _interfaces ??= new List(); _interfaces.Add(interfaceType); } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2083:DynamicallyAccessedMembers", Justification = "Not sure how to handle")] [return: DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] - protected override TypeInfo CreateTypeInfoCore() => this; - protected override ConstructorBuilder DefineConstructorCore(MethodAttributes attributes, CallingConventions callingConvention, Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers) => throw new NotImplementedException(); - protected override ConstructorBuilder DefineDefaultConstructorCore(MethodAttributes attributes) => throw new NotImplementedException(); + protected override TypeInfo CreateTypeInfoCore() + { + if (_isCreated) + { + return this; + } + + // Create a public default constructor if this class has no constructor. Except the type is Interface, ValueType, Enum, or a static class. + // (TypeAttributes.Abstract | TypeAttributes.Sealed) determines if the type is static + if (_constructorDefinitions.Count == 0 && (_attributes & TypeAttributes.Interface) == 0 && !IsValueType && + ((_attributes & (TypeAttributes.Abstract | TypeAttributes.Sealed)) != (TypeAttributes.Abstract | TypeAttributes.Sealed))) + { + DefineDefaultConstructor(MethodAttributes.Public); + } + + _module.PopulateTypeAndItsMembersTokens(this); + + _isCreated = true; + return this; + } + + internal void ThrowIfCreated() + { + if (_isCreated) + { + throw new InvalidOperationException(SR.InvalidOperation_TypeHasBeenCreated); + } + } + + protected override ConstructorBuilder DefineConstructorCore(MethodAttributes attributes, CallingConventions callingConvention, Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers) + { + if ((_attributes & TypeAttributes.Interface) == TypeAttributes.Interface && (attributes & MethodAttributes.Static) != MethodAttributes.Static) + { + throw new InvalidOperationException(SR.InvalidOperation_ConstructorNotAllowedOnInterface); + } + + ThrowIfCreated(); + + string name; + if ((attributes & MethodAttributes.Static) == 0) + { + name = ConstructorInfo.ConstructorName; + } + else + { + name = ConstructorInfo.TypeConstructorName; + } + + attributes |= MethodAttributes.SpecialName; + ConstructorBuilderImpl constBuilder = new ConstructorBuilderImpl(name, attributes, callingConvention, parameterTypes, _module, this); + _constructorDefinitions.Add(constBuilder); + return constBuilder; + } + + protected override ConstructorBuilder DefineDefaultConstructorCore(MethodAttributes attributes) + { + if ((_attributes & TypeAttributes.Interface) == TypeAttributes.Interface) + { + throw new InvalidOperationException(SR.InvalidOperation_ConstructorNotAllowedOnInterface); + } + + return DefineDefaultConstructorInternal(attributes); + } + + private ConstructorBuilderImpl DefineDefaultConstructorInternal(MethodAttributes attributes) + { + // Get the parent class's default constructor and add it to the IL + ConstructorInfo? con; + if (_typeParent!.IsConstructedGenericType && _typeParent.GetGenericTypeDefinition() is TypeBuilderImpl typeBuilder) + { + con = GetConstructor(_typeParent, typeBuilder.GetConstructor( + BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null)!); + } + else + { + con = _typeParent.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, EmptyTypes, null); + } + + if (con == null) + { + throw new NotSupportedException(SR.NotSupported_NoParentDefaultConstructor); + } + + ConstructorBuilderImpl constBuilder = (ConstructorBuilderImpl)DefineConstructorCore(attributes, CallingConventions.Standard, null, null, null); + + // generate the code to call the parent's default constructor + ILGenerator il = constBuilder.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Call, con); + il.Emit(OpCodes.Ret); + + constBuilder._isDefaultConstructor = true; + return constBuilder; + } + protected override EventBuilder DefineEventCore(string name, EventAttributes attributes, Type eventtype) => throw new NotImplementedException(); protected override FieldBuilder DefineFieldCore(string fieldName, Type type, Type[]? requiredCustomModifiers, Type[]? optionalCustomModifiers, FieldAttributes attributes) { + ThrowIfCreated(); + if (_enumUnderlyingType == null && IsEnum) { if ((attributes & FieldAttributes.Static) == 0) @@ -103,14 +200,16 @@ protected override FieldBuilder DefineFieldCore(string fieldName, Type type, Typ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names) { if (_typeParameters != null) + { throw new InvalidOperationException(); + } var typeParameters = new GenericTypeParameterBuilderImpl[names.Length]; for (int i = 0; i < names.Length; i++) { string name = names[i]; ArgumentNullException.ThrowIfNull(name, nameof(names)); - typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this, _handle); + typeParameters[i] = new GenericTypeParameterBuilderImpl(name, i, this); } return _typeParameters = typeParameters; @@ -120,6 +219,8 @@ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(par protected override MethodBuilder DefineMethodCore(string name, MethodAttributes attributes, CallingConventions callingConvention, Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) { + ThrowIfCreated(); + MethodBuilderImpl methodBuilder = new(name, attributes, callingConvention, returnType, parameterTypes, _module, this); _methodDefinitions.Add(methodBuilder); return methodBuilder; @@ -138,7 +239,7 @@ protected override TypeBuilder DefineNestedTypeCore(string name, TypeAttributes protected override PropertyBuilder DefinePropertyCore(string name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) => throw new NotImplementedException(); protected override ConstructorBuilder DefineTypeInitializerCore() => throw new NotImplementedException(); protected override FieldBuilder DefineUninitializedDataCore(string name, int size, FieldAttributes attributes) => throw new NotImplementedException(); - protected override bool IsCreatedCore() => false; + protected override bool IsCreatedCore() => _isCreated; protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan binaryAttribute) { // Handle pseudo custom attributes @@ -225,9 +326,11 @@ private void ParseStructLayoutAttribute(ConstructorInfo con, ReadOnlySpan } [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2074:DynamicallyAccessedMembers", - Justification = "TODO: Need to figure out how to preserve System.Object public constructor")] + Justification = "System.Object type is preserved via ModulBuilderImpl.s_coreTypes")] protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent) { + ThrowIfCreated(); + if (parent != null) { if (parent.IsInterface) @@ -259,10 +362,20 @@ protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAcc public override Type? DeclaringType => _declaringType; public override Type? ReflectedType => _declaringType; public override bool IsGenericTypeDefinition => IsGenericType; + public override bool IsConstructedGenericType => false; public override bool IsGenericType => _typeParameters != null; // Not returning a copy for compat with existing runtime behavior public override Type[] GenericTypeParameters => _typeParameters ?? EmptyTypes; public override Type[] GetGenericArguments() => _typeParameters ?? EmptyTypes; + public override Type GetGenericTypeDefinition() + { + if (IsGenericTypeDefinition) + { + return this; + } + + throw new InvalidOperationException(); + } public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException(); public override object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException(); public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException(); @@ -279,7 +392,9 @@ public override Type UnderlyingSystemType if (IsEnum) { if (_enumUnderlyingType == null) + { throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum); + } return _enumUnderlyingType; } @@ -305,11 +420,98 @@ protected override bool IsCOMObjectImpl() { return ((GetAttributeFlagsImpl() & TypeAttributes.Import) != 0) ? true : false; } + + internal void ThrowIfNotCreated() + { + if (!_isCreated) + { + throw new NotSupportedException(SR.NotSupported_TypeNotYetCreated); + } + } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder, - CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) => throw new NotSupportedException(); + CallingConventions callConvention, Type[] types, ParameterModifier[]? _) + { + ThrowIfNotCreated(); + ArgumentNullException.ThrowIfNull(types); + + for (int i = 0; i < types.Length; i++) + { + ArgumentNullException.ThrowIfNull(types[i], nameof(types)); + } + + foreach (ConstructorBuilderImpl con in _constructorDefinitions) + { + if (MatchesTheFilter(con._methodBuilder, con._methodBuilder.GetBindingFlags(), bindingAttr, callConvention, types)) + { + return con; + } + } + + return null; + } + + private static bool MatchesTheFilter(MethodBuilderImpl method, BindingFlags ctorFlags, BindingFlags bindingFlags, CallingConventions callConv, Type[]? argumentTypes) + { + if ((bindingFlags & ctorFlags) != ctorFlags) + { + return false; + } + + if ((callConv & CallingConventions.Any) == 0) + { + if ((callConv & CallingConventions.VarArgs) != 0 && (method.CallingConvention & CallingConventions.VarArgs) == 0) + { + return false; + } + + if ((callConv & CallingConventions.Standard) != 0 && (method.CallingConvention & CallingConventions.Standard) == 0) + { + return false; + } + } + + Type[] parameterTypes = method.ParameterTypes ?? EmptyTypes; + + if (argumentTypes == null) + { + return parameterTypes.Length == 0; + } + + if (argumentTypes.Length != parameterTypes.Length) + { + return false; + } + + for (int i = 0; i < parameterTypes.Length; i++) + { + if (argumentTypes[i] != parameterTypes[i]) + { + return false; + } + } + + return true; + } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => throw new NotSupportedException(); + public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) + { + ThrowIfNotCreated(); + + List ctors = new(); + foreach (ConstructorBuilderImpl con in _constructorDefinitions) + { + if (MatchesTheFilter(con._methodBuilder, con._methodBuilder.GetBindingFlags(), bindingAttr, CallingConventions.Any, con._methodBuilder.ParameterTypes)) + { + ctors.Add(con); + } + } + + return ctors.ToArray(); + } + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)] public override EventInfo[] GetEvents() => throw new NotSupportedException(); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveConstructorBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveConstructorBuilderTests.cs new file mode 100644 index 0000000000000..2802ae1520ae2 --- /dev/null +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveConstructorBuilderTests.cs @@ -0,0 +1,191 @@ +// 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.IO; +using System.Linq; +using Xunit; + +namespace System.Reflection.Emit.Tests +{ + [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))] + public class AssemblySaveConstructorBuilderTests + { + [Fact] + public void DefineConstructorsTest() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + ConstructorBuilder constructor = type.DefineDefaultConstructor(MethodAttributes.Public); + ConstructorBuilder constructor2 = type.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(int) }); + ILGenerator il = constructor2.GetILGenerator(); + il.Emit(OpCodes.Ret); + type.CreateType(); + + ConstructorInfo[] ctors = type.GetConstructors(); + Assert.Equal(2, ctors.Length); + + Assert.Equal(constructor, type.GetConstructor(Type.EmptyTypes)); + Assert.Equal(ctors[0], type.GetConstructor(Type.EmptyTypes)); + Assert.Equal(ctors[1], type.GetConstructor(new[] { typeof(int) })); + Assert.Null(type.GetConstructor(new[] { typeof(string) })); + } + + [Fact] + public void DefineDefaultConstructor_WithTypeBuilderParent() + { + AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + type.CreateType(); + TypeBuilder child = ab.GetDynamicModule("MyModule").DefineType("ChildType", TypeAttributes.Public | TypeAttributes.Class); + child.SetParent(type); + child.DefineDefaultConstructor(MethodAttributes.Family); + child.CreateType(); + + ConstructorInfo[] ctors = child.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance); + Assert.Equal(1, ctors.Length); + Assert.True(ctors[0].IsFamily); + Assert.Empty(child.GetConstructors(BindingFlags.Public | BindingFlags.Instance)); + } + + [Fact] + public void DefineDefaultConstructor_GenericParentCreated_Works() + { + AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + type.DefineGenericParameters("T"); + ConstructorBuilder constructor = type.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); + FieldBuilder field = type.DefineField("TestField", typeof(bool), FieldAttributes.Public | FieldAttributes.Static); + ILGenerator constructorILGenerator = constructor.GetILGenerator(); + constructorILGenerator.Emit(OpCodes.Ldarg_0); + constructorILGenerator.Emit(OpCodes.Ldc_I4_1); + constructorILGenerator.Emit(OpCodes.Stfld, field); + constructorILGenerator.Emit(OpCodes.Ret); + type.CreateType(); + + Assert.True(type.IsGenericTypeDefinition); + Assert.Equal("T", type.GetGenericTypeDefinition().GetGenericArguments()[0].Name); + + Type genericParent = type.MakeGenericType(typeof(int)); + TypeBuilder derived = ((ModuleBuilder)type.Module).DefineType("Derived"); + derived.SetParent(genericParent); + derived.DefineDefaultConstructor(MethodAttributes.Public); + + Type genericList = typeof(List<>).MakeGenericType(typeof(int)); + TypeBuilder type2 = ab.GetDynamicModule("MyModule").DefineType("Type2"); + type2.SetParent(genericList); + type2.DefineDefaultConstructor(MethodAttributes.Public); + type2.CreateTypeInfo(); + + Assert.NotNull(type2.GetConstructor(Type.EmptyTypes)); + } + + [Fact] + public void DefineDefaultConstructor_Interface_ThrowsInvalidOperationException() + { + AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(new AssemblyName("MyAssembly"), null, typeof(string), out var _); + TypeBuilder type = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Interface | TypeAttributes.Abstract); + Assert.Throws(() => type.DefineDefaultConstructor(MethodAttributes.Public)); + } + + [Fact] + public void DefineDefaultConstructor_ThrowsNotSupportedException_IfParentNotCreated() + { + AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + TypeBuilder child = ab.GetDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public); + child.SetParent(type); + Assert.Throws(() => child.DefineDefaultConstructor(MethodAttributes.Public)); + } + + [Fact] + public void DefineDefaultConstructor_StaticVirtual_ThrowsArgumentException() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo saveMethod); + AssertExtensions.Throws(null, () => type.DefineDefaultConstructor(MethodAttributes.Virtual | MethodAttributes.Static)); + } + + [Fact] + public void DefineDefaultConstructor_ParentNoDefaultConstructor_ThrowsNotSupportedException() + { + AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + FieldBuilder field = type.DefineField("TestField", typeof(int), FieldAttributes.Family); + + ConstructorBuilder constructor = type.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { typeof(int) }); + ILGenerator constructorIlGenerator = constructor.GetILGenerator(); + constructorIlGenerator.Emit(OpCodes.Ldarg_0); + constructorIlGenerator.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); + constructorIlGenerator.Emit(OpCodes.Ldarg_0); + constructorIlGenerator.Emit(OpCodes.Ldarg_1); + constructorIlGenerator.Emit(OpCodes.Stfld, field); + constructorIlGenerator.Emit(OpCodes.Ret); + + TypeBuilder derivedType = ab.GetDynamicModule("MyModule").DefineType("DerivedType", TypeAttributes.Public | TypeAttributes.Class); + derivedType.SetParent(type); + + Assert.Throws(() => derivedType.DefineDefaultConstructor(MethodAttributes.Public)); + } + + [Theory] + [InlineData(MethodAttributes.Private)] + [InlineData(MethodAttributes.PrivateScope)] + public void DefineDefaultConstructor_ParentPrivateDefaultConstructor_ThrowsNotSupportedException(MethodAttributes attributes) + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder baseType, out MethodInfo _); + ConstructorBuilder constructor = baseType.DefineConstructor(attributes, CallingConventions.HasThis, new[] { typeof(int) }); + constructor.GetILGenerator().Emit(OpCodes.Ret); + + TypeBuilder type = ((ModuleBuilder)baseType.Module).DefineType("DerivedType", TypeAttributes.Public | TypeAttributes.Class); + type.SetParent(baseType); + Assert.Throws(() => type.DefineDefaultConstructor(MethodAttributes.Public)); + } + + [Fact] + public void GetConstructor_DeclaringTypeOfConstructorGenericTypeDefinition() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + type.DefineGenericParameters("T"); + + ConstructorBuilder ctor = type.DefineDefaultConstructor(MethodAttributes.PrivateScope | MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName); + var constructor = TypeBuilder.GetConstructor(type, ctor); + Assert.False(constructor.IsGenericMethodDefinition); + } + + [Fact] + public void TypeBuilder_GetConstructorWorks() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + type.DefineGenericParameters("T"); + + ConstructorBuilder ctor = type.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.RTSpecialName); + + Type genericIntType = type.MakeGenericType(typeof(int)); + ConstructorInfo constructor = TypeBuilder.GetConstructor(genericIntType, ctor); + Assert.Equal(ctor.MetadataToken, constructor.MetadataToken); + Assert.Equal(ctor.Attributes, constructor.Attributes); + } + + [Fact] + public void GetConstructor_DeclaringTypeOfConstructorNotGenericTypeDefinitionOfType_ThrowsArgumentException() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type1, out MethodInfo _); + type1.DefineGenericParameters("T"); + + TypeBuilder type2 = ((ModuleBuilder)type1.Module).DefineType("TestType2", TypeAttributes.Class | TypeAttributes.Public); + type2.DefineGenericParameters("T"); + + ConstructorBuilder ctor1 = type1.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName); + ConstructorBuilder ctor2 = type2.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName); + + Type genericInt = type1.MakeGenericType(typeof(int)); + AssertExtensions.Throws("type", () => TypeBuilder.GetConstructor(genericInt, ctor2)); + } + + [Fact] + public void GetConstructor_TypeNotGeneric_ThrowsArgumentException() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + + ConstructorBuilder ctor = type.DefineDefaultConstructor(MethodAttributes.Public); + + AssertExtensions.Throws("constructor", () => TypeBuilder.GetConstructor(type.AsType(), ctor)); + } + } +} diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs index a43222afe34f0..7d7191c8c365a 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs @@ -140,6 +140,7 @@ private static void PopulateMembersForModule(ModuleBuilder mb, Type[] types, Lis DefineMethodsAndSetAttributes(methodAttributes, tb, type.IsInterface ? type.GetMethods() : type.GetMethods(BindingFlags.DeclaredOnly), methodAttributes); DefineFieldsAndSetAttributes(fieldAttributes, type.GetFields(), tb); + tb.CreateType(); } } @@ -196,6 +197,7 @@ public void CreateStructWithPseudoCustomAttributesTest() TypeBuilder tb = ab.DefineDynamicModule("Module").DefineType(type.FullName, type.Attributes, type.BaseType); DefineFieldsAndSetAttributes(fieldAttributes.ToList(), type.GetFields(), tb); typeAttributes.ForEach(tb.SetCustomAttribute); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -284,6 +286,7 @@ public void InterfacesWithPseudoCustomAttributes() TypeBuilder tb = ab.DefineDynamicModule("Module").DefineType(type.FullName, type.Attributes); typeAttributes.ForEach(tb.SetCustomAttribute); DefineMethodsAndSetAttributes(methodAttributes, tb, type.GetMethods(), parameterAttributes); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -435,6 +438,7 @@ public void MarshalAsPseudoCustomAttributesTest(CustomAttributeBuilder attribute FieldInfo stringField = type.GetFields()[1]; FieldBuilder fb = tb.DefineField(stringField.Name, stringField.FieldType, stringField.Attributes); fb.SetCustomAttribute(attribute); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -472,6 +476,7 @@ public void EnumBuilderSetCustomAttributesTest() CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(attributeConstructor, new object[] { true }); enumBuilder.SetCustomAttribute(attributeBuilder); enumBuilder.SetCustomAttribute(new CustomAttributeBuilder(s_guidPair.con, s_guidPair.args)); + enumBuilder.CreateTypeInfo(); saveMethod.Invoke(ab, new object[] { file.Path }); Type testEnum = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestEnum"); diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveEnumBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveEnumBuilderTests.cs index 0fddcb4f54b98..7616f526b7a02 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveEnumBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveEnumBuilderTests.cs @@ -64,8 +64,10 @@ public void DefineLiteral(Type underlyingType, object literalValue) { using (TempFile file = TempFile.Create()) { - EnumBuilder enumBuilder = CreateAssemblyAndDefineEnum(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod, out TypeBuilder _, underlyingType); + EnumBuilder enumBuilder = CreateAssemblyAndDefineEnum(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod, out TypeBuilder type, underlyingType); FieldBuilder literal = enumBuilder.DefineLiteral("FieldOne", literalValue); + enumBuilder.CreateTypeInfo(); + type.CreateTypeInfo(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -97,6 +99,8 @@ public void SaveArrayTypeSignature(int rank, string name) MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public); mb.SetReturnType(arrayType); mb.SetParameters(new Type[] { typeof(INoMethod), arrayType }); + enumBuilder.CreateType(); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestInterface"); @@ -135,6 +139,8 @@ public void SaveByRefTypeSignature() MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public); mb.SetReturnType(byrefType); mb.SetParameters(new Type[] { typeof(INoMethod), byrefType }); + eb.CreateType(); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestInterface"); @@ -162,6 +168,8 @@ public void SavePointerTypeSignature() MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public); mb.SetReturnType(pointerType); mb.SetParameters(new Type[] { typeof(INoMethod), pointerType }); + eb.CreateType(); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestInterface"); diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveILGeneratorTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveILGeneratorTests.cs index 0cc6c140cd4dc..a5d646811c76d 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveILGeneratorTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveILGeneratorTests.cs @@ -19,6 +19,7 @@ public void MethodWithEmptyBody() MethodBuilder methodBuilder = type.DefineMethod("EmptyMethod", MethodAttributes.Public, typeof(void), new[] { typeof(Version) }); ILGenerator il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ret); + type.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -48,6 +49,7 @@ public void MethodReturning_Int(int size) int expectedReturn = 5; ilGenerator.Emit(OpCodes.Ldc_I4, expectedReturn); ilGenerator.Emit(OpCodes.Ret); + type.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -86,7 +88,7 @@ public void TypeWithTwoMethod_ReferenceMethodArguments(int multiplier) addMethodIL.Emit(OpCodes.Ldarg_1); addMethodIL.Emit(OpCodes.Add); addMethodIL.Emit(OpCodes.Ret); - + type.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -125,7 +127,7 @@ public void MultipleTypesWithMultipleMethods() addMethodIL.Emit(OpCodes.Ldc_R8, (double)123456.123); addMethodIL.Emit(OpCodes.Add); addMethodIL.Emit(OpCodes.Ret); - + type.CreateType(); TypeBuilder anotherType = ab.GetDynamicModule("MyModule").DefineType("AnotherType", TypeAttributes.NotPublic); MethodBuilder stringMethod = anotherType.DefineMethod("StringMethod", MethodAttributes.FamORAssem, typeof(string), Type.EmptyTypes); MethodBuilder floatMethod = anotherType.DefineMethod("FloatMethod", MethodAttributes.Family, typeof(float), Type.EmptyTypes); @@ -140,7 +142,7 @@ public void MultipleTypesWithMultipleMethods() ILGenerator longMethodIL = longMethod.GetILGenerator(); longMethodIL.Emit(OpCodes.Ldc_I8, (long)1234567); longMethodIL.Emit(OpCodes.Ret); - + anotherType.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -223,7 +225,7 @@ public void ILMaxStack_Test() il2.Emit(OpCodes.Add); // pop 2 push 1 stack size 2 il2.Emit(OpCodes.Add); // pop 2 push 1 stack size 1 il2.Emit(OpCodes.Ret); // pop 1 stack size 0 - + type.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); MethodInfo getMaxStackSizeMethod = LoadILGenerator_GetMaxStackSizeMethod(); @@ -274,7 +276,7 @@ public void Label_ConditionalBranching() il.Emit(OpCodes.Ldc_I4_M1); il.MarkLabel(endOfMethod); il.Emit(OpCodes.Ret); - + type.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); MethodInfo getMaxStackSizeMethod = LoadILGenerator_GetMaxStackSizeMethod(); @@ -345,7 +347,7 @@ public void Label_SwitchCase() il.Emit(OpCodes.Ldstr, "many bananas"); il.MarkLabel(endOfMethod); il.Emit(OpCodes.Ret); - + type.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); MethodInfo getMaxStackSizeMethod = LoadILGenerator_GetMaxStackSizeMethod(); @@ -392,7 +394,7 @@ public void LocalBuilderMultipleLocalsUsage() il.Emit(OpCodes.Stloc, int2Local); il.Emit(OpCodes.Ldloc_3); il.Emit(OpCodes.Ret); - + type.CreateType(); MethodInfo getMaxStackSizeMethod = LoadILGenerator_GetMaxStackSizeMethod(); Assert.Equal(2, getMaxStackSizeMethod.Invoke(il, new object[0])); saveMethod.Invoke(ab, new object[] { file.Path }); @@ -481,7 +483,7 @@ public void LocalBuilderMultipleTypesWithMultipleMethodsWithLocals() multiplyMethodIL.Emit(OpCodes.Stloc, iLocal); multiplyMethodIL.Emit(OpCodes.Ldloc, iLocal); multiplyMethodIL.Emit(OpCodes.Ret); - + type.CreateType(); TypeBuilder anotherType = ab.GetDynamicModule("MyModule").DefineType("AnotherType", TypeAttributes.NotPublic, type); MethodBuilder stringMethod = anotherType.DefineMethod("StringMethod", MethodAttributes.FamORAssem, typeof(string), Type.EmptyTypes); ILGenerator stringMethodIL = stringMethod.GetILGenerator(); @@ -514,7 +516,7 @@ public void LocalBuilderMultipleTypesWithMultipleMethodsWithLocals() longMethodIL.Emit(OpCodes.Stloc, longLocal); longMethodIL.Emit(OpCodes.Ldloc, longLocal); longMethodIL.Emit(OpCodes.Ret); - + anotherType.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -559,6 +561,7 @@ public void ReferenceFieldInIL() il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Mul); il.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -620,7 +623,7 @@ void Main(int a) ilMain.Emit(OpCodes.Box, typeof(int)); ilMain.Emit(OpCodes.Call, writeLineObj); ilMain.Emit(OpCodes.Ret); - + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -650,6 +653,133 @@ void Main(int a) } } + [Fact] + public void ReferenceConstructedGenericMethod() + { + using (TempFile file = TempFile.Create()) + { + AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo saveMethod); + ConstructorBuilder ctor = type.DefineDefaultConstructor(MethodAttributes.Public); + MethodBuilder genericMethod = type.DefineMethod("GM", MethodAttributes.Public | MethodAttributes.Static); + GenericTypeParameterBuilder[] methodParams = genericMethod.DefineGenericParameters("U"); + genericMethod.SetSignature(null, null, null, new[] { methodParams[0] }, null, null); + ILGenerator ilg = genericMethod.GetILGenerator(); + MethodInfo writeLineObj = typeof(Console).GetMethod("WriteLine", new[] { typeof(object) }); + ilg.Emit(OpCodes.Ldarg_0); + ilg.EmitCall(OpCodes.Call, writeLineObj, null); + ilg.Emit(OpCodes.Ret); + MethodBuilder mainMethod = type.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static); + ilg = mainMethod.GetILGenerator(); + MethodInfo GMOfString = genericMethod.MakeGenericMethod(typeof(string)); + ilg.Emit(OpCodes.Ldstr, "Hello, world!"); + ilg.EmitCall(OpCodes.Call, GMOfString, null); + ilg.Emit(OpCodes.Ret); + type.CreateType(); + saveMethod.Invoke(ab, new[] { file.Path }); + + Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); + Type typeFromDisk = assemblyFromDisk.Modules.First().GetType("MyType"); + MethodInfo genericMethodFromDisk = typeFromDisk.GetMethod("GM"); + Assert.True(genericMethodFromDisk.IsGenericMethod); + Assert.True(genericMethodFromDisk.IsGenericMethodDefinition); + byte[] ilBytes = typeFromDisk.GetMethod("Main").GetMethodBody().GetILAsByteArray(); + Assert.Equal(OpCodes.Ldstr.Value, ilBytes[0]); + Assert.Equal(OpCodes.Call.Value, ilBytes[5]); + Assert.Equal(OpCodes.Ret.Value, ilBytes[10]); + } + } + + [Fact] + public void ReferenceConstructedGenericMethodFieldOfConstructedType() + { + using (TempFile file = TempFile.Create()) + { + AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo saveMethod); + GenericTypeParameterBuilder[] typeParams = type.DefineGenericParameters(new[] { "T" }); + ConstructorBuilder ctor = type.DefineDefaultConstructor(MethodAttributes.PrivateScope | MethodAttributes.Public | + MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName); + FieldBuilder myField = type.DefineField("Field", typeParams[0], FieldAttributes.Public); + MethodBuilder genericMethod = type.DefineMethod("GM", MethodAttributes.Public | MethodAttributes.Static); + GenericTypeParameterBuilder[] methodParams = genericMethod.DefineGenericParameters("U"); + genericMethod.SetSignature(null, null, null, new [] { methodParams[0] }, null, null); + ILGenerator ilg = genericMethod.GetILGenerator(); + Type SampleOfU = type.MakeGenericType(methodParams[0]); + ilg.DeclareLocal(SampleOfU); + ConstructorInfo ctorOfU = TypeBuilder.GetConstructor(SampleOfU, ctor); + ilg.Emit(OpCodes.Newobj, ctorOfU); + ilg.Emit(OpCodes.Stloc_0); + ilg.Emit(OpCodes.Ldloc_0); + ilg.Emit(OpCodes.Ldarg_0); + FieldInfo FieldOfU = TypeBuilder.GetField(SampleOfU, myField); + ilg.Emit(OpCodes.Stfld, FieldOfU); + ilg.Emit(OpCodes.Ldloc_0); + ilg.Emit(OpCodes.Ldfld, FieldOfU); + ilg.Emit(OpCodes.Box, methodParams[0]); + MethodInfo writeLineObj = typeof(Console).GetMethod("WriteLine", new[] { typeof(object) }); + ilg.EmitCall(OpCodes.Call, writeLineObj, null); + ilg.Emit(OpCodes.Ret); + type.CreateType(); + TypeBuilder dummy = ab.GetDynamicModule("MyModule").DefineType("Dummy", TypeAttributes.Class | TypeAttributes.NotPublic); + MethodBuilder mainMethod = dummy.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static); + ilg = mainMethod.GetILGenerator(); + Type SampleOfInt = type.MakeGenericType(typeof(string)); + MethodInfo SampleOfIntGM = TypeBuilder.GetMethod(SampleOfInt, genericMethod); + MethodInfo GMOfString = SampleOfIntGM.MakeGenericMethod(typeof(string)); + ilg.Emit(OpCodes.Ldstr, "Hello, world!"); + ilg.EmitCall(OpCodes.Call, GMOfString, null); + ilg.Emit(OpCodes.Ret); + dummy.CreateType(); +/* Generated IL would like this in C#: +public class MyType +{ + public T Field; + + public static void GM(U P_0) + { + MyType myType = new MyType(); + myType.Field = P_0; + Console.WriteLine(myType.Field); + } +} + +internal class Dummy +{ + public static void Main() + { + MyType.GM("HelloWorld"); + } +} */ + saveMethod.Invoke(ab, new[] { file.Path }); + + Module module = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First(); + Type myTypeFromDisk = module.GetType("MyType"); + Assert.True(myTypeFromDisk.IsGenericType); + Assert.True(myTypeFromDisk.IsGenericTypeDefinition); + Assert.Equal("T", myTypeFromDisk.GetGenericArguments()[0].Name); + Assert.Equal("T", myTypeFromDisk.GetField("Field").FieldType.Name); + MethodInfo genericMethodFromDisk = myTypeFromDisk.GetMethod("GM"); + Assert.True(genericMethodFromDisk.IsGenericMethod); + Assert.True(genericMethodFromDisk.IsGenericMethodDefinition); + Assert.Equal(1, genericMethodFromDisk.GetMethodBody().LocalVariables.Count); + Assert.Equal("MyType[U]", genericMethodFromDisk.GetMethodBody().LocalVariables[0].LocalType.ToString()); + byte[] gmIlBytes = genericMethodFromDisk.GetMethodBody().GetILAsByteArray(); + Assert.Equal(OpCodes.Newobj.Value, gmIlBytes[0]); + Assert.Equal(OpCodes.Stloc_0.Value, gmIlBytes[5]); + Assert.Equal(OpCodes.Ldloc_0.Value, gmIlBytes[6]); + Assert.Equal(OpCodes.Ldarg_0.Value, gmIlBytes[7]); + Assert.Equal(OpCodes.Stfld.Value, gmIlBytes[8]); + Assert.Equal(OpCodes.Ldloc_0.Value, gmIlBytes[13]); + Assert.Equal(OpCodes.Ldfld.Value, gmIlBytes[14]); + Assert.Equal(OpCodes.Box.Value, gmIlBytes[19]); + Assert.Equal(OpCodes.Call.Value, gmIlBytes[24]); + Assert.Equal(OpCodes.Ret.Value, gmIlBytes[29]); + byte[] ilBytes = module.GetType("Dummy").GetMethod("Main").GetMethodBody().GetILAsByteArray(); + Assert.Equal(OpCodes.Ldstr.Value, ilBytes[0]); + Assert.Equal(OpCodes.Call.Value, ilBytes[5]); + Assert.Equal(OpCodes.Ret.Value, ilBytes[10]); + } + } + [Fact] public void EmitWriteLineMacroTest() { @@ -669,7 +799,7 @@ public void EmitWriteLineMacroTest() ilGenerator.EmitWriteLine(local); ilGenerator.Emit(OpCodes.Ldsfld, field); ilGenerator.Emit(OpCodes.Ret); - + type1.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -727,7 +857,8 @@ void static StaticMethod() { } ilMain.Emit(OpCodes.Ret); ILGenerator il = staticMethod.GetILGenerator(); il.Emit(OpCodes.Ret); - + tb.CreateType(); + anotherType.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -758,7 +889,7 @@ public void ReferenceConstructorInIL() il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Newobj, ctor); il.Emit(OpCodes.Ret); - + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -784,7 +915,7 @@ public void ReferenceAType() ilGenerator.Emit(OpCodes.Initobj, typeof(ValueTuple)); ilGenerator.Emit(OpCodes.Ldc_I4, 1); ilGenerator.Emit(OpCodes.Ret); - + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -849,6 +980,7 @@ public void SimpleTryCatchBlock() ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -901,6 +1033,7 @@ public void TryMultipleCatchBlocks() ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -976,6 +1109,7 @@ public void TryFilterCatchBlock() ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -1038,6 +1172,7 @@ public void TryCatchFilterCatchBlock() ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -1071,6 +1206,7 @@ public void TryFinallyBlock() ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -1111,6 +1247,7 @@ public void TryCatchFinallyBlock() ilGenerator.EmitWriteLine("Finally handler"); ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -1174,6 +1311,7 @@ public void TryFilterCatchFinallyBlock() myAdderIL.MarkLabel(myEndOfMethodLabel); myAdderIL.Emit(OpCodes.Ldloc_S, myLocalBuilder1); myAdderIL.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -1207,6 +1345,7 @@ public void TryFaultBlock() ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -1259,6 +1398,7 @@ public void NestedTryCatchBlocks() ilGenerator.EmitWriteLine("Outer catch block ends"); ilGenerator.EndExceptionBlock(); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -1331,6 +1471,7 @@ public void DeeperNestedTryCatchFilterFinallyBlocks() ilGenerator.Emit(OpCodes.Ldloc_0); ilGenerator.Emit(OpCodes.Ret); + tb.CreateType(); saveMethod.Invoke(ab, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTools.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTools.cs index f63eb084abcf0..6f92cc3a6e855 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTools.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTools.cs @@ -47,6 +47,8 @@ private static void PopulateMembersForModule(ModuleBuilder mb, Type[] types) { tb.DefineField(field.Name, field.FieldType, field.Attributes); } + + tb.CreateType(); } } @@ -64,7 +66,7 @@ internal static void WriteAssemblyToStream(AssemblyName assemblyName, Type[] typ internal static AssemblyBuilder PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder typeBuilder, out MethodInfo saveMethod) { AssemblyBuilder ab = PopulateAssemblyBuilderAndSaveMethod(s_assemblyName, null, typeof(string), out saveMethod); - typeBuilder = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public); + typeBuilder = ab.DefineDynamicModule("MyModule").DefineType("MyType", TypeAttributes.Public | TypeAttributes.Class); return ab; } diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTypeBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTypeBuilderTests.cs index 7a76202fc8a8d..aea10712990ec 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTypeBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveTypeBuilderTests.cs @@ -74,7 +74,7 @@ private static void AssertTypesAndTypeMembers(Type[] types, Type[] typesFromDisk Type typeFromDisk = typesFromDisk[i]; AssemblySaveTools.AssertTypeProperties(sourceType, typeFromDisk); - AssemblySaveTools.AssertMethods(sourceType.GetMethods(), typeFromDisk.GetMethods()); + AssemblySaveTools.AssertMethods(sourceType.GetMethods(BindingFlags.DeclaredOnly), typeFromDisk.GetMethods(BindingFlags.DeclaredOnly)); AssemblySaveTools.AssertFields(sourceType.GetFields(), typeFromDisk.GetFields()); } } @@ -99,6 +99,7 @@ public void CreateMembersThatUsesTypeLoadedFromCoreAssemblyTest() { TypeBuilder tb = CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod); tb.DefineMethod("TestMethod", MethodAttributes.Public); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -134,7 +135,9 @@ public void AddInterfaceImplementationTest() ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module"); TypeBuilder tb = mb.DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract, null, new Type[] { typeof(IOneMethod)}); tb.AddInterfaceImplementation(typeof(INoMethod)); - tb.DefineNestedType("NestedType", TypeAttributes.Interface | TypeAttributes.Abstract); + TypeBuilder nestedType = tb.DefineNestedType("NestedType", TypeAttributes.Interface | TypeAttributes.Abstract); + tb.CreateType(); + nestedType.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path); @@ -172,6 +175,7 @@ public void SaveGenericTypeParametersForAType(string[] typeParamNames) { SetVariousGenericParameterValues(typeParams); } + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0]; @@ -235,6 +239,7 @@ public void SaveGenericTypeParametersForAMethod(string[] typeParamNames) { SetVariousGenericParameterValues(typeParams); } + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0]; @@ -265,6 +270,7 @@ public void SaveArrayTypeSignature(int rank, string name) MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public); mb.SetReturnType(arrayType); mb.SetParameters(new Type[] { typeof(INoMethod), arrayType, typeof(int[,,,]) }); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0]; @@ -298,6 +304,7 @@ public void SaveByRefTypeSignature() MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public); mb.SetReturnType(byrefType); mb.SetParameters(new Type[] { typeof(INoMethod), byrefType }); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0]; @@ -325,6 +332,7 @@ public void SavePointerTypeSignature() MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public); mb.SetReturnType(pointerType); mb.SetParameters(new Type[] { typeof(INoMethod), pointerType }); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0]; @@ -362,6 +370,7 @@ public void SaveGenericTypeSignature(string[] genericParams, Type[] typeArgument MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public); mb.SetReturnType(genericType); mb.SetParameters(new Type[] { typeof(INoMethod), genericType }); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0]; @@ -374,6 +383,49 @@ public void SaveGenericTypeSignature(string[] genericParams, Type[] typeArgument } } + [Fact] + public void TypeBuilder_GetMethod_ReturnsMethod() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + type.DefineGenericParameters("T"); + + MethodBuilder genericMethod = type.DefineMethod("GM", MethodAttributes.Public | MethodAttributes.Static); + GenericTypeParameterBuilder[] methodParams = genericMethod.DefineGenericParameters("U"); + genericMethod.SetParameters(new[] { methodParams[0] }); + + Type genericIntType = type.MakeGenericType(typeof(int)); + MethodInfo createdConstructedTypeMethod = TypeBuilder.GetMethod(genericIntType, genericMethod); + MethodInfo createdGenericMethod = TypeBuilder.GetMethod(type, genericMethod); + + Assert.True(createdConstructedTypeMethod.IsGenericMethodDefinition); + Assert.True(createdGenericMethod.IsGenericMethodDefinition); + Assert.Equal("Type: U", createdConstructedTypeMethod.GetGenericArguments()[0].ToString()); + Assert.Equal("Type: U", createdGenericMethod.GetGenericArguments()[0].ToString()); + } + + [Fact] + public void TypeBuilder_GetField_DeclaringTypeOfFieldGeneric() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + GenericTypeParameterBuilder[] typeParams = type.DefineGenericParameters("T"); + + FieldBuilder field = type.DefineField("Field", typeParams[0].AsType(), FieldAttributes.Public); + FieldBuilder field2 = type.DefineField("Field2", typeParams[0], FieldAttributes.Public); + Type genericIntType = type.MakeGenericType(typeof(int)); + + Assert.Equal("Field", TypeBuilder.GetField(type.AsType(), field).Name); + Assert.Equal("Field2", TypeBuilder.GetField(genericIntType, field2).Name); + } + + [Fact] + public void GetField_TypeNotGeneric_ThrowsArgumentException() + { + AssemblySaveTools.PopulateAssemblyBuilderTypeBuilderAndSaveMethod(out TypeBuilder type, out MethodInfo _); + FieldBuilder field = type.DefineField("Field", typeof(int), FieldAttributes.Public); + + AssertExtensions.Throws("field", () => TypeBuilder.GetField(type, field)); + } + private static void AssertGenericType(string stringRepresentation, Type paramType) { Assert.True(paramType.IsGenericType); @@ -396,6 +448,7 @@ public void SaveGenericTypeSignatureWithGenericParameter() Type genericType = tb.MakeGenericType(typeParams); mb.SetReturnType(methodParams[0]); mb.SetParameters(new Type[] { typeof(INoMethod), genericType, typeParams[1] }); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0]; @@ -430,13 +483,13 @@ public void SaveMultipleGenericTypeParametersToEnsureSortingWorks() ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module"); TypeBuilder tb = mb.DefineType("TestInterface1", TypeAttributes.Interface | TypeAttributes.Abstract); GenericTypeParameterBuilder[] typeParams = tb.DefineGenericParameters(new string[] { "U", "T" }); - typeParams[1].SetInterfaceConstraints(new Type[] { typeof(INoMethod), typeof(IOneMethod) }); + typeParams[1].SetInterfaceConstraints(new [] { typeof(INoMethod), typeof(IOneMethod) }); MethodBuilder m11 = tb.DefineMethod("TwoParameters", MethodAttributes.Public); MethodBuilder m12 = tb.DefineMethod("FiveTypeParameters", MethodAttributes.Public); MethodBuilder m13 = tb.DefineMethod("OneParameter", MethodAttributes.Public); m11.DefineGenericParameters(new string[] { "M", "N" }); GenericTypeParameterBuilder[] methodParams = m12.DefineGenericParameters(new string[] { "A", "B", "C", "D", "F" }); - methodParams[2].SetInterfaceConstraints(new Type[] { typeof(IMultipleMethod) }); + methodParams[2].SetInterfaceConstraints(new [] { typeof(IMultipleMethod) }); m13.DefineGenericParameters(new string[] { "T" }); TypeBuilder tb2 = mb.DefineType("TestInterface2", TypeAttributes.Interface | TypeAttributes.Abstract); tb2.DefineGenericParameters(new string[] { "TFirst", "TSecond", "TThird" }); @@ -445,12 +498,15 @@ public void SaveMultipleGenericTypeParametersToEnsureSortingWorks() TypeBuilder tb3 = mb.DefineType("TestType"); GenericTypeParameterBuilder[] typePar = tb3.DefineGenericParameters(new string[] { "TOne" }); typePar[0].SetBaseTypeConstraint(typeof(EmptyTestClass)); + tb3.CreateType(); + tb2.CreateType(); + tb.CreateType(); saveMethod.Invoke(assemblyBuilder, new object[] { file.Path }); Module m = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First(); - Type[] type1Params = m.GetTypes()[0].GetGenericArguments(); + Type[] type1Params = m.GetTypes()[2].GetGenericArguments(); Type[] type2Params = m.GetTypes()[1].GetGenericArguments(); - Type[] type3Params = m.GetTypes()[2].GetGenericArguments(); + Type[] type3Params = m.GetTypes()[0].GetGenericArguments(); Assert.Equal("U", type1Params[0].Name); Assert.Empty(type1Params[0].GetTypeInfo().GetGenericParameterConstraints()); @@ -462,10 +518,10 @@ public void SaveMultipleGenericTypeParametersToEnsureSortingWorks() Assert.Equal("TOne", type3Params[0].Name); Assert.Equal(nameof(EmptyTestClass), type3Params[0].GetTypeInfo().GetGenericParameterConstraints()[0].Name); - Type[] method11Params = m.GetTypes()[0].GetMethod("TwoParameters").GetGenericArguments(); - Type[] method12Params = m.GetTypes()[0].GetMethod("FiveTypeParameters").GetGenericArguments(); + Type[] method11Params = m.GetTypes()[2].GetMethod("TwoParameters").GetGenericArguments(); + Type[] method12Params = m.GetTypes()[2].GetMethod("FiveTypeParameters").GetGenericArguments(); Assert.Equal(nameof(IMultipleMethod), method12Params[2].GetTypeInfo().GetGenericParameterConstraints()[0].Name); - Type[] method13Params = m.GetTypes()[0].GetMethod("OneParameter").GetGenericArguments(); + Type[] method13Params = m.GetTypes()[2].GetMethod("OneParameter").GetGenericArguments(); Type[] method21Params = m.GetTypes()[1].GetMethod("TestMethod").GetGenericArguments(); Assert.Equal("M", method11Params[0].Name); diff --git a/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj b/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj index 74471dbc3164d..912e5ba52c505 100644 --- a/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj +++ b/src/libraries/System.Reflection.Emit/tests/System.Reflection.Emit.Tests.csproj @@ -63,6 +63,7 @@ + diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs index cb8beb606f1b8..4e35723cc5ad4 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs @@ -44,110 +44,6 @@ namespace System.Reflection.Emit { - public abstract partial class TypeBuilder - { - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "Linker thinks Type.GetConstructor(ConstructorInfo) is one of the public APIs because it doesn't analyze method signatures. We already have ConstructorInfo.")] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "Type.MakeGenericType is used to create a typical instantiation")] - public static ConstructorInfo GetConstructor(Type type, ConstructorInfo constructor) - { - if (!IsValidGetMethodType(type)) - throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); - - if (type is TypeBuilder && type.ContainsGenericParameters) - type = type.MakeGenericType(type.GetGenericArguments()); - - if (!constructor.DeclaringType!.IsGenericTypeDefinition) - throw new ArgumentException(SR.Argument_ConstructorNeedGenericDeclaringType, nameof(constructor)); - - if (constructor.DeclaringType != type.GetGenericTypeDefinition()) - throw new ArgumentException(SR.Argument_InvalidConstructorDeclaringType, nameof(type)); - - ConstructorInfo res = type.GetConstructor(constructor); - if (res == null) - throw new ArgumentException(SR.Format(SR.MissingConstructor_Name, type)); - - return res; - } - - private static bool IsValidGetMethodType(Type type) - { - if (type == null) - return false; - - if (type is TypeBuilder || type is TypeBuilderInstantiation) - return true; - /*GetMethod() must work with TypeBuilders after CreateType() was called.*/ - if (type.Module is ModuleBuilder) - return true; - if (type.IsGenericParameter) - return false; - - Type[] inst = type.GetGenericArguments(); - if (inst == null) - return false; - for (int i = 0; i < inst.Length; ++i) - { - if (IsValidGetMethodType(inst[i])) - return true; - } - return false; - } - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "Type.MakeGenericType is used to create a typical instantiation")] - public static MethodInfo GetMethod(Type type, MethodInfo method) - { - if (!IsValidGetMethodType(type)) - throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); - - if (type is TypeBuilder && type.ContainsGenericParameters) - type = type.MakeGenericType(type.GetGenericArguments()); - - if (method.IsGenericMethod && !method.IsGenericMethodDefinition) - throw new ArgumentException(SR.Argument_NeedGenericMethodDefinition, nameof(method)); - - if (!method.DeclaringType!.IsGenericTypeDefinition) - throw new ArgumentException(SR.Argument_MethodNeedGenericDeclaringType, nameof(method)); - - if (method.DeclaringType != type.GetGenericTypeDefinition()) - throw new ArgumentException(SR.Argument_InvalidMethodDeclaringType, nameof(type)); - - MethodInfo res = type.GetMethod(method); - if (res == null) - throw new ArgumentException(SR.Format(SR.MissingMethod_Name, type, method.Name)); - - return res; - } - - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2055:UnrecognizedReflectionPattern", - Justification = "Type.MakeGenericType is used to create a typical instantiation")] - public static FieldInfo GetField(Type type, FieldInfo field) - { - if (!IsValidGetMethodType(type)) - throw new ArgumentException(SR.Argument_MustBeTypeBuilder, nameof(type)); - - if (type is TypeBuilder && type.ContainsGenericParameters) - type = type.MakeGenericType(type.GetGenericArguments()); - - if (!field.DeclaringType!.IsGenericTypeDefinition) - throw new ArgumentException(SR.Argument_FieldNeedGenericDeclaringType, nameof(field)); - - if (field.DeclaringType != type.GetGenericTypeDefinition()) - throw new ArgumentException(SR.Argument_InvalidFieldDeclaringType, nameof(type)); - - if (field is FieldOnTypeBuilderInstantiation) - throw new ArgumentException(SR.Argument_FieldNeedGenericDeclaringType, nameof(field)); - - FieldInfo res = type.GetField(field); - if (res == null) - throw new System.Exception(SR.Format(SR.MissingField, field.Name)); - else - return res; - } - } - [StructLayout(LayoutKind.Sequential)] internal sealed partial class RuntimeTypeBuilder : TypeBuilder {