diff --git a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx index 6103dbef1f159d..8ec0577d1f8ea8 100644 --- a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx @@ -303,4 +303,7 @@ Unmatching symbol scope. + + Type provided must be an Enum. + \ No newline at end of file diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs index f9f85f90b2aa57..8d0561d15be47b 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs @@ -40,78 +40,10 @@ internal FieldBuilderImpl(TypeBuilderImpl typeBuilder, string fieldName, Type ty protected override void SetConstantCore(object? defaultValue) { _typeBuilder.ThrowIfCreated(); - ValidateDefaultValueType(defaultValue, _fieldType); _defaultValue = defaultValue; _attributes |= FieldAttributes.HasDefault; } - internal static void ValidateDefaultValueType(object? defaultValue, Type destinationType) - { - if (defaultValue == null) - { - // nullable value types can hold null value. - if (destinationType.IsValueType && !(destinationType.IsGenericType && destinationType.GetGenericTypeDefinition() == typeof(Nullable<>))) - { - throw new ArgumentException(SR.Argument_ConstantNull); - } - } - else - { - Type sourceType = defaultValue.GetType(); - // We should allow setting a constant value on a ByRef parameter - if (destinationType.IsByRef) - { - destinationType = destinationType.GetElementType()!; - } - - // Convert nullable types to their underlying type. - destinationType = Nullable.GetUnderlyingType(destinationType) ?? destinationType; - - if (destinationType.IsEnum) - { - Type underlyingType; - if (destinationType is EnumBuilderImpl enumBldr) - { - underlyingType = enumBldr.GetEnumUnderlyingType(); - - if (sourceType != enumBldr._typeBuilder.UnderlyingSystemType && - sourceType != underlyingType && - // If the source type is an enum, should not throw when the underlying types match - sourceType.IsEnum && - sourceType.GetEnumUnderlyingType() != underlyingType) - { - throw new ArgumentException(SR.Argument_ConstantDoesntMatch); - } - } - else if (destinationType is TypeBuilderImpl typeBldr) - { - underlyingType = typeBldr.UnderlyingSystemType; - - if (underlyingType == null || (sourceType != typeBldr.UnderlyingSystemType && sourceType != underlyingType)) - { - throw new ArgumentException(SR.Argument_ConstantDoesntMatch); - } - } - else - { - underlyingType = Enum.GetUnderlyingType(destinationType); - - if (sourceType != destinationType && sourceType != underlyingType) - { - throw new ArgumentException(SR.Argument_ConstantDoesntMatch); - } - } - } - else - { - if (!destinationType.IsAssignableFrom(sourceType)) - { - throw new ArgumentException(SR.Argument_ConstantDoesntMatch); - } - } - } - } - internal void SetData(byte[] data) { _rvaData = data; 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 93040c155f2074..f1b6446be8e0f8 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 @@ -32,8 +32,6 @@ public ParameterBuilderImpl(MethodBuilderImpl methodBuilder, int sequence, Param public override void SetConstant(object? defaultValue) { - Type parameterType = _position == 0 ? _methodBuilder.ReturnType : _methodBuilder.ParameterTypes![_position - 1]; - FieldBuilderImpl.ValidateDefaultValueType(defaultValue, parameterType); _defaultValue = defaultValue; _attributes |= ParameterAttributes.HasDefault; } diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PropertyBuilderImpl.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PropertyBuilderImpl.cs index 68cc5a813451d3..faf1538a1a8e84 100644 --- a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PropertyBuilderImpl.cs +++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/PropertyBuilderImpl.cs @@ -57,7 +57,6 @@ protected override void AddOtherMethodCore(MethodBuilder mdBuilder) protected override void SetConstantCore(object? defaultValue) { _containingType.ThrowIfCreated(); - FieldBuilderImpl.ValidateDefaultValueType(defaultValue, _propertyType); _defaultValue = defaultValue; } 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 c4480d7cee5538..0a5075a60d9a6e 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 @@ -616,23 +616,22 @@ public override Type GetGenericTypeDefinition() public override string? Namespace => _namespace; public override Assembly Assembly => _module.Assembly; public override Module Module => _module; - public override Type UnderlyingSystemType + public override Type UnderlyingSystemType => this; + + public override Type GetEnumUnderlyingType() { - get + if (IsEnum) { - if (IsEnum) + if (_enumUnderlyingType == null) { - if (_enumUnderlyingType == null) - { - throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum); - } - - return _enumUnderlyingType; - } - else - { - return this; + throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum); } + + return _enumUnderlyingType; + } + else + { + throw new ArgumentException(SR.Argument_MustBeEnum); } } public override bool IsSZArray => false; diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveEnumBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveEnumBuilderTests.cs index 17a64d34ef2bc7..b10126675568e3 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveEnumBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySaveEnumBuilderTests.cs @@ -37,7 +37,7 @@ public static IEnumerable DefineLiteral_TestData() yield return new object[] { typeof(uint), (uint)1 }; yield return new object[] { typeof(int), 0 }; - yield return new object[] { typeof(int), 1 }; + yield return new object[] { typeof(int), Test.Second }; yield return new object[] { typeof(ulong), (ulong)0 }; yield return new object[] { typeof(ulong), (ulong)1 }; diff --git a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySavePropertyBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySavePropertyBuilderTests.cs index 06caf8dbb6a7de..a8cd0754c853fb 100644 --- a/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySavePropertyBuilderTests.cs +++ b/src/libraries/System.Reflection.Emit/tests/PersistedAssemblyBuilder/AssemblySavePropertyBuilderTests.cs @@ -163,6 +163,24 @@ public void SetConstantVariousValues(Type returnType, object defaultValue) Assert.Equal(defaultValue, property.GetConstantValue()); } + [Theory] + [MemberData(nameof(SetConstant_TestData))] + public void SetConstantVariousValuesMlcCoreAssembly(Type returnType, object defaultValue) + { + using (MetadataLoadContext mlc = new MetadataLoadContext(new CoreMetadataAssemblyResolver())) + { + PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("MyDynamicAssembly"), mlc.CoreAssembly); + ModuleBuilder mb = ab.DefineDynamicModule("My Module"); + Type returnTypeFromCore = returnType != typeof(PropertyBuilderTest11.Colors) ? mlc.CoreAssembly.GetType(returnType.FullName, true) : returnType; + TypeBuilder type = mb.DefineType("MyType", TypeAttributes.Public); + + PropertyBuilder property = type.DefineProperty("TestProperty", PropertyAttributes.HasDefault, returnTypeFromCore, null); + property.SetConstant(defaultValue); + + Assert.Equal(defaultValue, property.GetConstantValue()); + } + } + [Fact] public void SetCustomAttribute_ConstructorInfo_ByteArray_NullConstructorInfo_ThrowsArgumentNullException() { @@ -194,7 +212,6 @@ public void Set_WhenTypeAlreadyCreated_ThrowsInvalidOperationException() MethodAttributes getMethodAttributes = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; MethodBuilder method = type.DefineMethod("TestMethod", getMethodAttributes, typeof(int), null); method.GetILGenerator().Emit(OpCodes.Ret); - AssertExtensions.Throws(() => property.SetConstant((decimal)10)); CustomAttributeBuilder customAttrBuilder = new CustomAttributeBuilder(typeof(IntPropertyAttribute).GetConstructor([typeof(int)]), [10]); type.CreateType(); @@ -204,18 +221,5 @@ public void Set_WhenTypeAlreadyCreated_ThrowsInvalidOperationException() Assert.Throws(() => property.SetConstant(1)); Assert.Throws(() => property.SetCustomAttribute(customAttrBuilder)); } - - [Fact] - public void SetConstant_ValidationThrows() - { - AssemblySaveTools.PopulateAssemblyBuilderAndTypeBuilder(out TypeBuilder type); - FieldBuilder field = type.DefineField("TestField", typeof(int), FieldAttributes.Private); - PropertyBuilder property = type.DefineProperty("TestProperty", PropertyAttributes.HasDefault, typeof(int), null); - - AssertExtensions.Throws(() => property.SetConstant((decimal)10)); - AssertExtensions.Throws(() => property.SetConstant(null)); - type.CreateType(); - Assert.Throws(() => property.SetConstant(1)); - } } }