Skip to content

Commit 3eb6eef

Browse files
buyaa-njkotas
andauthored
Add EnumBuilder implementation and other changes (#88503)
* Add EnumBuilder implementation and other changes * Update src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/EnumBuilderImpl.cs Co-authored-by: Jan Kotas <[email protected]> * Apply feedback --------- Co-authored-by: Jan Kotas <[email protected]>
1 parent 563a549 commit 3eb6eef

File tree

16 files changed

+894
-104
lines changed

16 files changed

+894
-104
lines changed

src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -292,35 +292,6 @@ public override bool IsDefined(Type attributeType, bool inherit)
292292
return m_typeBuilder.IsDefined(attributeType, inherit);
293293
}
294294

295-
/*****************************************************
296-
*
297-
* private/protected functions
298-
*
299-
*/
300-
301-
public override Type MakePointerType()
302-
{
303-
return SymbolType.FormCompoundType("*", this, 0)!;
304-
}
305-
306-
public override Type MakeByRefType()
307-
{
308-
return SymbolType.FormCompoundType("&", this, 0)!;
309-
}
310-
311-
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
312-
public override Type MakeArrayType()
313-
{
314-
return SymbolType.FormCompoundType("[]", this, 0)!;
315-
}
316-
317-
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
318-
public override Type MakeArrayType(int rank)
319-
{
320-
string s = GetRankString(rank);
321-
return SymbolType.FormCompoundType(s, this, 0)!;
322-
}
323-
324295
// Constructs a EnumBuilder.
325296
// EnumBuilder can only be a top-level (not nested) enum type.
326297
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2064:UnrecognizedReflectionPattern",

src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,28 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
3939

4040
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
4141
=> SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
42+
43+
public override Type MakePointerType()
44+
{
45+
return SymbolType.FormCompoundType("*", this, 0)!;
46+
}
47+
48+
public override Type MakeByRefType()
49+
{
50+
return SymbolType.FormCompoundType("&", this, 0)!;
51+
}
52+
53+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
54+
public override Type MakeArrayType()
55+
{
56+
return SymbolType.FormCompoundType("[]", this, 0)!;
57+
}
58+
59+
[RequiresDynamicCode("The code for an array of the specified type might not be available.")]
60+
public override Type MakeArrayType(int rank)
61+
{
62+
string s = GetRankString(rank);
63+
return SymbolType.FormCompoundType(s, this, 0)!;
64+
}
4265
}
4366
}

src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Microsoft Visual Studio Solution File, Format Version 12.00
1+
Microsoft Visual Studio Solution File, Format Version 12.00
22
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{772C93D4-FC45-46AA-B09F-26F01B672EDC}"
33
EndProject
44
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{E5543842-139D-43BD-B604-E65EBB91649E}"
@@ -596,4 +596,4 @@ Global
596596
GlobalSection(ExtensibilityGlobals) = postSolution
597597
SolutionGuid = {739AA767-154B-4C69-8C9B-C3D332833D92}
598598
EndGlobalSection
599-
EndGlobal
599+
EndGlobal

src/libraries/System.Reflection.Emit/src/Resources/Strings.resx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,4 +171,16 @@
171171
<data name="InvalidOperation_GenericParametersAlreadySet" xml:space="preserve">
172172
<value>The generic parameters are already defined on this MethodBuilder.</value>
173173
</data>
174+
<data name="Argument_ShouldOnlySetVisibilityFlags" xml:space="preserve">
175+
<value>Should only set visibility flags when creating EnumBuilder.</value>
176+
</data>
177+
<data name="Argument_ConstantDoesntMatch" xml:space="preserve">
178+
<value>Constant does not match the defined type.</value>
179+
</data>
180+
<data name="Argument_ConstantNull" xml:space="preserve">
181+
<value>Null is not a valid constant value for this type.</value>
182+
</data>
183+
<data name="InvalidOperation_NoUnderlyingTypeOnEnum" xml:space="preserve">
184+
<value>Underlying type information on enumeration is not specified.</value>
185+
</data>
174186
</root>

src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
<ItemGroup>
88
<Compile Include="System\Reflection\Emit\CustomAttributeWrapper.cs" />
99
<Compile Include="System\Reflection\Emit\AssemblyBuilderImpl.cs" />
10+
<Compile Include="System\Reflection\Emit\EnumBuilderImpl.cs" />
1011
<Compile Include="System\Reflection\Emit\FieldBuilderImpl.cs" />
1112
<Compile Include="System\Reflection\Emit\GenericTypeParameterBuilderImpl.cs" />
1213
<Compile Include="System\Reflection\Emit\MethodBuilderImpl.cs" />
1314
<Compile Include="System\Reflection\Emit\ModuleBuilderImpl.cs" />
1415
<Compile Include="System\Reflection\Emit\ParameterBuilderImpl.cs" />
1516
<Compile Include="System\Reflection\Emit\PseudoCustomAttributesData.cs" />
16-
<Compile Include="System\Reflection\Emit\TypeBuilderImpl.cs" />
1717
<Compile Include="System\Reflection\Emit\SignatureHelper.cs" />
18+
<Compile Include="System\Reflection\Emit\TypeBuilderImpl.cs" />
19+
<Compile Include="System\Reflection\Emit\TypeNameBuilder.cs" />
1820
</ItemGroup>
1921
<ItemGroup>
2022
<ProjectReference Include="$(CoreLibProject)" />
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.Diagnostics.CodeAnalysis;
5+
using System.Reflection.Metadata;
6+
7+
namespace System.Reflection.Emit
8+
{
9+
internal sealed class EnumBuilderImpl : EnumBuilder
10+
{
11+
private readonly FieldBuilder _underlyingField;
12+
internal readonly TypeBuilderImpl _typeBuilder;
13+
14+
internal EnumBuilderImpl(string name, Type underlyingType, TypeAttributes visibility, ModuleBuilderImpl module, TypeDefinitionHandle typeHandle)
15+
{
16+
if ((visibility & ~TypeAttributes.VisibilityMask) != 0)
17+
throw new ArgumentException(SR.Argument_ShouldOnlySetVisibilityFlags, nameof(name));
18+
19+
_typeBuilder = new TypeBuilderImpl(name, visibility | TypeAttributes.Sealed, typeof(Enum), module, typeHandle, null, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize, null);
20+
21+
// Define the underlying field for the enum. It will be a non-static, private field with special name bit set.
22+
_underlyingField = _typeBuilder.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName);
23+
}
24+
25+
protected override FieldBuilder UnderlyingFieldCore => _underlyingField;
26+
27+
[return: DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))]
28+
protected override TypeInfo CreateTypeInfoCore() => _typeBuilder.CreateTypeInfo();
29+
30+
protected override FieldBuilder DefineLiteralCore(string literalName, object? literalValue)
31+
{
32+
FieldBuilder fieldBuilder = _typeBuilder.DefineField(
33+
literalName,
34+
_typeBuilder,
35+
FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
36+
fieldBuilder.SetConstant(literalValue);
37+
return fieldBuilder;
38+
}
39+
40+
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute) =>
41+
_typeBuilder.SetCustomAttribute(con, binaryAttribute);
42+
43+
public override Guid GUID => _typeBuilder.GUID;
44+
45+
public override string Name => _typeBuilder.Name;
46+
47+
public override Module Module => _typeBuilder.Module;
48+
49+
public override Assembly Assembly => _typeBuilder.Assembly;
50+
51+
public override RuntimeTypeHandle TypeHandle => _typeBuilder.TypeHandle;
52+
53+
public override string? FullName => _typeBuilder.FullName;
54+
55+
public override string? AssemblyQualifiedName => _typeBuilder.AssemblyQualifiedName;
56+
57+
public override string? Namespace => _typeBuilder.Namespace;
58+
59+
public override Type? BaseType => _typeBuilder.BaseType;
60+
61+
public override bool IsByRefLike => false;
62+
63+
public override bool IsTypeDefinition => true;
64+
65+
public override bool IsSZArray => false;
66+
67+
public override bool IsConstructedGenericType => false;
68+
69+
public override Type? DeclaringType => _typeBuilder.DeclaringType;
70+
71+
public override Type? ReflectedType => _typeBuilder.ReflectedType;
72+
73+
public override Type UnderlyingSystemType => GetEnumUnderlyingType();
74+
75+
public override Type GetEnumUnderlyingType() => _underlyingField.FieldType;
76+
77+
protected override bool IsArrayImpl() => false;
78+
79+
protected override bool IsPrimitiveImpl() => false;
80+
81+
protected override bool IsValueTypeImpl() => true;
82+
83+
protected override bool IsByRefImpl() => false;
84+
85+
protected override bool IsPointerImpl() => false;
86+
87+
protected override bool IsCOMObjectImpl() => false;
88+
89+
public override Type? GetElementType() => _typeBuilder.GetElementType();
90+
91+
protected override bool HasElementTypeImpl() => _typeBuilder.HasElementType;
92+
93+
protected override TypeAttributes GetAttributeFlagsImpl() => _typeBuilder.Attributes;
94+
95+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
96+
public override Type[] GetInterfaces() => EmptyTypes;
97+
98+
public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();
99+
public override object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException();
100+
public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException();
101+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
102+
public override object? InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target,
103+
object?[]? args, ParameterModifier[]? modifiers, Globalization.CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException();
104+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
105+
protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder,
106+
CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) => throw new NotSupportedException();
107+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
108+
public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => throw new NotSupportedException();
109+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)]
110+
public override EventInfo[] GetEvents() => throw new NotSupportedException();
111+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
112+
public override EventInfo[] GetEvents(BindingFlags bindingAttr) => throw new NotSupportedException();
113+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
114+
public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) => throw new NotSupportedException();
115+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
116+
public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => throw new NotSupportedException();
117+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
118+
protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder,
119+
CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException();
120+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
121+
public override FieldInfo? GetField(string name, BindingFlags bindingAttr) => throw new NotSupportedException();
122+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
123+
public override FieldInfo[] GetFields(BindingFlags bindingAttr) => throw new NotSupportedException();
124+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
125+
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
126+
public override Type? GetInterface(string name, bool ignoreCase) => throw new NotSupportedException();
127+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
128+
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => throw new NotSupportedException();
129+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
130+
protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder,
131+
Type? returnType, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException();
132+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
133+
public override Type[] GetNestedTypes(BindingFlags bindingAttr) => throw new NotSupportedException();
134+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
135+
public override Type? GetNestedType(string name, BindingFlags bindingAttr) => throw new NotSupportedException();
136+
[DynamicallyAccessedMembers(TypeBuilderImpl.GetAllMembers)]
137+
public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) => throw new NotSupportedException();
138+
public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType)
139+
=> throw new NotSupportedException();
140+
[DynamicallyAccessedMembers(TypeBuilderImpl.GetAllMembers)]
141+
public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotSupportedException();
142+
public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) => throw new NotSupportedException();
143+
}
144+
}

src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/FieldBuilderImpl.cs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ internal sealed class FieldBuilderImpl : FieldBuilder
2222
internal MarshallingData? _marshallingData;
2323
internal int _offset;
2424
internal List<CustomAttributeWrapper>? _customAttributes;
25+
internal object? _defaultValue = DBNull.Value;
2526

2627
internal FieldBuilderImpl(TypeBuilderImpl typeBuilder, string fieldName, Type type, FieldAttributes attributes)
2728
{
@@ -32,7 +33,61 @@ internal FieldBuilderImpl(TypeBuilderImpl typeBuilder, string fieldName, Type ty
3233
_offset = -1;
3334
}
3435

35-
protected override void SetConstantCore(object? defaultValue) => throw new NotImplementedException();
36+
protected override void SetConstantCore(object? defaultValue)
37+
{
38+
if (defaultValue == null)
39+
{
40+
// nullable value types can hold null value.
41+
if (_fieldType.IsValueType && !(_fieldType.IsGenericType && _fieldType.GetGenericTypeDefinition() == typeof(Nullable<>)))
42+
throw new ArgumentException(SR.Argument_ConstantNull);
43+
}
44+
else
45+
{
46+
Type type = defaultValue.GetType();
47+
Type destType = _fieldType;
48+
49+
// We should allow setting a constant value on a ByRef parameter
50+
if (destType.IsByRef)
51+
destType = destType.GetElementType()!;
52+
53+
// Convert nullable types to their underlying type.
54+
destType = Nullable.GetUnderlyingType(destType) ?? destType;
55+
56+
if (destType.IsEnum)
57+
{
58+
Type underlyingType;
59+
if (destType is EnumBuilderImpl enumBldr)
60+
{
61+
underlyingType = enumBldr.GetEnumUnderlyingType();
62+
63+
if (type != enumBldr._typeBuilder.UnderlyingSystemType && type != underlyingType)
64+
throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
65+
}
66+
else if (destType is TypeBuilderImpl typeBldr)
67+
{
68+
underlyingType = typeBldr.UnderlyingSystemType;
69+
70+
if (underlyingType == null || (type != typeBldr.UnderlyingSystemType && type != underlyingType))
71+
throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
72+
}
73+
else
74+
{
75+
underlyingType = Enum.GetUnderlyingType(destType);
76+
77+
if (type != destType && type != underlyingType)
78+
throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
79+
}
80+
}
81+
else
82+
{
83+
if (!destType.IsAssignableFrom(type))
84+
throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
85+
}
86+
87+
_defaultValue = defaultValue;
88+
}
89+
}
90+
3691
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
3792
{
3893
// Handle pseudo custom attributes

0 commit comments

Comments
 (0)