diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs
index 1d0703dc51c02e..c54ded37c10e95 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs
@@ -292,35 +292,6 @@ public override bool IsDefined(Type attributeType, bool inherit)
return m_typeBuilder.IsDefined(attributeType, inherit);
}
- /*****************************************************
- *
- * private/protected functions
- *
- */
-
- public override Type MakePointerType()
- {
- return SymbolType.FormCompoundType("*", this, 0)!;
- }
-
- public override Type MakeByRefType()
- {
- return SymbolType.FormCompoundType("&", this, 0)!;
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public override Type MakeArrayType()
- {
- return SymbolType.FormCompoundType("[]", this, 0)!;
- }
-
- [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
- public override Type MakeArrayType(int rank)
- {
- string s = GetRankString(rank);
- return SymbolType.FormCompoundType(s, this, 0)!;
- }
-
// Constructs a EnumBuilder.
// EnumBuilder can only be a top-level (not nested) enum type.
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2064:UnrecognizedReflectionPattern",
diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs
index 8017aabdcdb52c..e013510453c281 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/EnumBuilder.cs
@@ -39,5 +39,28 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
=> SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
+
+ public override Type MakePointerType()
+ {
+ return SymbolType.FormCompoundType("*", this, 0)!;
+ }
+
+ public override Type MakeByRefType()
+ {
+ return SymbolType.FormCompoundType("&", this, 0)!;
+ }
+
+ [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
+ public override Type MakeArrayType()
+ {
+ return SymbolType.FormCompoundType("[]", this, 0)!;
+ }
+
+ [RequiresDynamicCode("The code for an array of the specified type might not be available.")]
+ public override Type MakeArrayType(int rank)
+ {
+ string s = GetRankString(rank);
+ return SymbolType.FormCompoundType(s, this, 0)!;
+ }
}
}
diff --git a/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln b/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln
index 7a5969e89e2c85..b774027405c401 100644
--- a/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln
+++ b/src/libraries/System.Reflection.Emit/System.Reflection.Emit.sln
@@ -1,4 +1,4 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
+Microsoft Visual Studio Solution File, Format Version 12.00
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Private.CoreLib", "..\..\coreclr\System.Private.CoreLib\System.Private.CoreLib.csproj", "{772C93D4-FC45-46AA-B09F-26F01B672EDC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtilities", "..\Common\tests\TestUtilities\TestUtilities.csproj", "{E5543842-139D-43BD-B604-E65EBB91649E}"
@@ -596,4 +596,4 @@ Global
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {739AA767-154B-4C69-8C9B-C3D332833D92}
EndGlobalSection
-EndGlobal
+EndGlobal
\ No newline at end of file
diff --git a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx
index 5ff83e0f7b86d4..54123a4d079f2f 100644
--- a/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx
+++ b/src/libraries/System.Reflection.Emit/src/Resources/Strings.resx
@@ -171,4 +171,16 @@
The generic parameters are already defined on this MethodBuilder.
+
+ Should only set visibility flags when creating EnumBuilder.
+
+
+ Constant does not match the defined type.
+
+
+ Null is not a valid constant value for this type.
+
+
+ Underlying type information on enumeration is not specified.
+
\ 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 16e302c4efce12..dac4ca741abbc0 100644
--- a/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj
+++ b/src/libraries/System.Reflection.Emit/src/System.Reflection.Emit.csproj
@@ -7,14 +7,16 @@
+
-
+
+
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
new file mode 100644
index 00000000000000..b11a3cb2989d18
--- /dev/null
+++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/EnumBuilderImpl.cs
@@ -0,0 +1,144 @@
+// 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.CodeAnalysis;
+using System.Reflection.Metadata;
+
+namespace System.Reflection.Emit
+{
+ 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)
+ {
+ 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);
+
+ // 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);
+ }
+
+ protected override FieldBuilder UnderlyingFieldCore => _underlyingField;
+
+ [return: DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))]
+ protected override TypeInfo CreateTypeInfoCore() => _typeBuilder.CreateTypeInfo();
+
+ protected override FieldBuilder DefineLiteralCore(string literalName, object? literalValue)
+ {
+ FieldBuilder fieldBuilder = _typeBuilder.DefineField(
+ literalName,
+ _typeBuilder,
+ FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal);
+ fieldBuilder.SetConstant(literalValue);
+ return fieldBuilder;
+ }
+
+ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan binaryAttribute) =>
+ _typeBuilder.SetCustomAttribute(con, binaryAttribute);
+
+ public override Guid GUID => _typeBuilder.GUID;
+
+ public override string Name => _typeBuilder.Name;
+
+ public override Module Module => _typeBuilder.Module;
+
+ public override Assembly Assembly => _typeBuilder.Assembly;
+
+ public override RuntimeTypeHandle TypeHandle => _typeBuilder.TypeHandle;
+
+ public override string? FullName => _typeBuilder.FullName;
+
+ public override string? AssemblyQualifiedName => _typeBuilder.AssemblyQualifiedName;
+
+ public override string? Namespace => _typeBuilder.Namespace;
+
+ public override Type? BaseType => _typeBuilder.BaseType;
+
+ public override bool IsByRefLike => false;
+
+ public override bool IsTypeDefinition => true;
+
+ public override bool IsSZArray => false;
+
+ public override bool IsConstructedGenericType => false;
+
+ public override Type? DeclaringType => _typeBuilder.DeclaringType;
+
+ public override Type? ReflectedType => _typeBuilder.ReflectedType;
+
+ public override Type UnderlyingSystemType => GetEnumUnderlyingType();
+
+ public override Type GetEnumUnderlyingType() => _underlyingField.FieldType;
+
+ protected override bool IsArrayImpl() => false;
+
+ protected override bool IsPrimitiveImpl() => false;
+
+ protected override bool IsValueTypeImpl() => true;
+
+ protected override bool IsByRefImpl() => false;
+
+ protected override bool IsPointerImpl() => false;
+
+ protected override bool IsCOMObjectImpl() => false;
+
+ public override Type? GetElementType() => _typeBuilder.GetElementType();
+
+ protected override bool HasElementTypeImpl() => _typeBuilder.HasElementType;
+
+ protected override TypeAttributes GetAttributeFlagsImpl() => _typeBuilder.Attributes;
+
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
+ public override Type[] GetInterfaces() => EmptyTypes;
+
+ 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();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
+ public override object? InvokeMember(string name, BindingFlags invokeAttr, Binder? binder, object? target,
+ object?[]? args, ParameterModifier[]? modifiers, Globalization.CultureInfo? culture, string[]? namedParameters) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
+ protected override ConstructorInfo? GetConstructorImpl(BindingFlags bindingAttr, Binder? binder,
+ CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)]
+ public override ConstructorInfo[] GetConstructors(BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)]
+ public override EventInfo[] GetEvents() => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
+ public override EventInfo[] GetEvents(BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)]
+ public override EventInfo? GetEvent(string name, BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ public override MethodInfo[] GetMethods(BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)]
+ protected override MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder,
+ CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
+ public override FieldInfo? GetField(string name, BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)]
+ public override FieldInfo[] GetFields(BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
+ [return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
+ public override Type? GetInterface(string name, bool ignoreCase) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
+ public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
+ protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder,
+ Type? returnType, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
+ public override Type[] GetNestedTypes(BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)]
+ public override Type? GetNestedType(string name, BindingFlags bindingAttr) => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(TypeBuilderImpl.GetAllMembers)]
+ public override MemberInfo[] GetMember(string name, MemberTypes type, BindingFlags bindingAttr) => throw new NotSupportedException();
+ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] Type interfaceType)
+ => throw new NotSupportedException();
+ [DynamicallyAccessedMembers(TypeBuilderImpl.GetAllMembers)]
+ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) => throw new NotSupportedException();
+ public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) => throw new NotSupportedException();
+ }
+}
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 0e4fe230fb8cd2..39e8881c2ab8c5 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
@@ -22,6 +22,7 @@ internal sealed class FieldBuilderImpl : FieldBuilder
internal MarshallingData? _marshallingData;
internal int _offset;
internal List? _customAttributes;
+ internal object? _defaultValue = DBNull.Value;
internal FieldBuilderImpl(TypeBuilderImpl typeBuilder, string fieldName, Type type, FieldAttributes attributes)
{
@@ -32,7 +33,61 @@ internal FieldBuilderImpl(TypeBuilderImpl typeBuilder, string fieldName, Type ty
_offset = -1;
}
- protected override void SetConstantCore(object? defaultValue) => throw new NotImplementedException();
+ protected override void SetConstantCore(object? defaultValue)
+ {
+ if (defaultValue == null)
+ {
+ // nullable value types can hold null value.
+ if (_fieldType.IsValueType && !(_fieldType.IsGenericType && _fieldType.GetGenericTypeDefinition() == typeof(Nullable<>)))
+ throw new ArgumentException(SR.Argument_ConstantNull);
+ }
+ else
+ {
+ Type type = defaultValue.GetType();
+ Type destType = _fieldType;
+
+ // We should allow setting a constant value on a ByRef parameter
+ if (destType.IsByRef)
+ destType = destType.GetElementType()!;
+
+ // Convert nullable types to their underlying type.
+ destType = Nullable.GetUnderlyingType(destType) ?? destType;
+
+ if (destType.IsEnum)
+ {
+ Type underlyingType;
+ if (destType is EnumBuilderImpl enumBldr)
+ {
+ underlyingType = enumBldr.GetEnumUnderlyingType();
+
+ if (type != enumBldr._typeBuilder.UnderlyingSystemType && type != underlyingType)
+ throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
+ }
+ else if (destType is TypeBuilderImpl typeBldr)
+ {
+ underlyingType = typeBldr.UnderlyingSystemType;
+
+ if (underlyingType == null || (type != typeBldr.UnderlyingSystemType && type != underlyingType))
+ throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
+ }
+ else
+ {
+ underlyingType = Enum.GetUnderlyingType(destType);
+
+ if (type != destType && type != underlyingType)
+ throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
+ }
+ }
+ else
+ {
+ if (!destType.IsAssignableFrom(type))
+ throw new ArgumentException(SR.Argument_ConstantDoesntMatch);
+ }
+
+ _defaultValue = defaultValue;
+ }
+ }
+
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan binaryAttribute)
{
// Handle pseudo custom attributes
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 a135ed225785e8..c3ca6012544f34 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
@@ -247,6 +247,11 @@ private void WriteFields(TypeBuilderImpl typeBuilder)
{
AddMarshalling(fieldHandle, field._marshallingData.SerializeMarshallingData());
}
+
+ if (field._defaultValue != DBNull.Value)
+ {
+ AddDefaultValue(fieldHandle, field._defaultValue);
+ }
}
}
@@ -325,8 +330,8 @@ private void AddGenericTypeParametersAndConstraintsCustomAttributes(EntityHandle
}
}
- private void AddDefaultValue(ParameterHandle parameterHandle, object? defaultValue) =>
- _metadataBuilder.AddConstant(parent: parameterHandle, value: defaultValue);
+ private void AddDefaultValue(EntityHandle parentHandle, object? defaultValue) =>
+ _metadataBuilder.AddConstant(parent: parentHandle, value: defaultValue);
private FieldDefinitionHandle AddFieldDefinition(FieldBuilderImpl field, BlobBuilder fieldSignature) =>
_metadataBuilder.AddFieldDefinition(
@@ -407,6 +412,11 @@ internal EntityHandle GetTypeHandle(Type type)
return tb._handle;
}
+ if (type is EnumBuilderImpl eb && Equals(eb.Module))
+ {
+ return eb._typeBuilder._handle;
+ }
+
return GetTypeReference(type);
}
@@ -429,11 +439,19 @@ internal TypeBuilder DefineNestedType(string name, TypeAttributes attr, [Dynamic
public override int GetStringMetadataToken(string stringConstant) => throw new NotImplementedException();
public override int GetTypeMetadataToken(Type type) => throw new NotImplementedException();
protected override void CreateGlobalFunctionsCore() => throw new NotImplementedException();
- protected override EnumBuilder DefineEnumCore(string name, TypeAttributes visibility, Type underlyingType) => throw new NotImplementedException();
+
+ protected override EnumBuilder DefineEnumCore(string name, TypeAttributes visibility, Type underlyingType)
+ {
+ TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId);
+ EnumBuilderImpl enumBuilder = new EnumBuilderImpl(name, underlyingType, visibility, this, typeHandle);
+ _typeDefinitions.Add(enumBuilder._typeBuilder);
+ return enumBuilder;
+ }
protected override MethodBuilder DefineGlobalMethodCore(string name, MethodAttributes attributes, CallingConventions callingConvention, Type? returnType, Type[]? requiredReturnTypeCustomModifiers, Type[]? optionalReturnTypeCustomModifiers, Type[]? parameterTypes, Type[][]? requiredParameterTypeCustomModifiers, Type[][]? optionalParameterTypeCustomModifiers) => throw new NotImplementedException();
protected override FieldBuilder DefineInitializedDataCore(string name, byte[] data, FieldAttributes attributes) => throw new NotImplementedException();
[RequiresUnreferencedCode("P/Invoke marshalling may dynamically access members that could be trimmed.")]
protected override MethodBuilder DefinePInvokeMethodCore(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) => throw new NotImplementedException();
+
protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize)
{
@@ -442,6 +460,7 @@ protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr,
_typeDefinitions.Add(_type);
return _type;
}
+
protected override FieldBuilder DefineUninitializedDataCore(string name, int size, FieldAttributes attributes) => throw new NotImplementedException();
protected override MethodInfo GetArrayMethodCore(Type arrayClass, string methodName, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan binaryAttribute)
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 828f3a0820fb09..ba77906508ebbd 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
@@ -15,6 +15,7 @@ internal sealed class TypeBuilderImpl : TypeBuilder
private readonly ModuleBuilderImpl _module;
private readonly string _name;
private readonly string? _namespace;
+ private string? _strFullName;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
private Type? _typeParent;
private readonly TypeBuilderImpl? _declaringType;
@@ -22,6 +23,7 @@ internal sealed class TypeBuilderImpl : TypeBuilder
private TypeAttributes _attributes;
private PackingSize _packingSize;
private int _typeSize;
+ private Type? _enumUnderlyingType;
internal readonly TypeDefinitionHandle _handle;
internal readonly List _methodDefinitions = new();
@@ -73,14 +75,24 @@ protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembe
_interfaces.Add(interfaceType);
}
+ [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2083:DynamicallyAccessedMembers", Justification = "Not sure how to handle")]
[return: DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))]
- protected override TypeInfo CreateTypeInfoCore() => throw new NotImplementedException();
+ 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 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)
{
+ if (_enumUnderlyingType == null && IsEnum)
+ {
+ if ((attributes & FieldAttributes.Static) == 0)
+ {
+ // remember the underlying type for enum type
+ _enumUnderlyingType = type;
+ }
+ }
+
var field = new FieldBuilderImpl(this, fieldName, type, attributes);
_fieldDefinitions.Add(field);
return field;
@@ -156,6 +168,11 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
+ internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan binaryAttribute)
+ {
+ SetCustomAttributeCore(con, binaryAttribute);
+ }
+
private void ParseStructLayoutAttribute(ConstructorInfo con, ReadOnlySpan binaryAttribute)
{
CustomAttributeInfo attributeInfo = CustomAttributeInfo.DecodeCustomAttribute(con, binaryAttribute);
@@ -249,11 +266,27 @@ protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAcc
public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException();
public override Type GetElementType() => throw new NotSupportedException();
public override string? AssemblyQualifiedName => throw new NotSupportedException();
- public override string? FullName => throw new NotSupportedException();
+ public override string? FullName => _strFullName ??= TypeNameBuilder.ToString(this, TypeNameBuilder.Format.FullName);
public override string? Namespace => _namespace;
public override Assembly Assembly => _module.Assembly;
public override Module Module => _module;
- public override Type UnderlyingSystemType => this;
+ public override Type UnderlyingSystemType
+ {
+ get
+ {
+ if (IsEnum)
+ {
+ if (_enumUnderlyingType == null)
+ throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum);
+
+ return _enumUnderlyingType;
+ }
+ else
+ {
+ return this;
+ }
+ }
+ }
public override Guid GUID => throw new NotSupportedException();
public override Type? BaseType => _typeParent;
public override int MetadataToken => MetadataTokens.GetToken(_handle);
diff --git a/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeNameBuilder.cs b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeNameBuilder.cs
new file mode 100644
index 00000000000000..6297e14ca22ae0
--- /dev/null
+++ b/src/libraries/System.Reflection.Emit/src/System/Reflection/Emit/TypeNameBuilder.cs
@@ -0,0 +1,325 @@
+// 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.Text;
+
+namespace System.Reflection.Emit
+{
+ internal sealed class TypeNameBuilder
+ {
+ private readonly StringBuilder _str = new StringBuilder();
+ private int _instNesting;
+ private bool _firstInstArg;
+ private bool _nestedName;
+ private bool _hasAssemblySpec;
+ private readonly List _stack = new List();
+ private int _stackIdx;
+
+ private TypeNameBuilder()
+ {
+ }
+
+ private void OpenGenericArguments()
+ {
+ _instNesting++;
+ _firstInstArg = true;
+
+ Append('[');
+ }
+
+ private void CloseGenericArguments()
+ {
+ Debug.Assert(_instNesting != 0);
+
+ _instNesting--;
+
+ if (_firstInstArg)
+ {
+ _str.Remove(_str.Length - 1, 1);
+ }
+ else
+ {
+ Append(']');
+ }
+ }
+
+ private void OpenGenericArgument()
+ {
+ Debug.Assert(_instNesting != 0);
+
+ _nestedName = false;
+
+ if (!_firstInstArg)
+ Append(',');
+
+ _firstInstArg = false;
+
+ Append('[');
+
+ PushOpenGenericArgument();
+ }
+
+ private void CloseGenericArgument()
+ {
+ Debug.Assert(_instNesting != 0);
+
+ if (_hasAssemblySpec)
+ {
+ Append(']');
+ }
+
+ PopOpenGenericArgument();
+ }
+
+ private void AddName(string name)
+ {
+ Debug.Assert(name != null);
+
+ if (_nestedName)
+ Append('+');
+
+ _nestedName = true;
+
+ EscapeName(name);
+ }
+
+ private void AddArray(int rank)
+ {
+ Debug.Assert(rank > 0);
+
+ if (rank == 1)
+ {
+ Append("[*]");
+ }
+ else if (rank > 64)
+ {
+ // Only taken in an error path, runtime will not load arrays of more than 32 dimensions
+ _str.Append('[').Append(rank).Append(']');
+ }
+ else
+ {
+ Append('[');
+ for (int i = 1; i < rank; i++)
+ Append(',');
+ Append(']');
+ }
+ }
+
+ private void AddAssemblySpec(string assemblySpec)
+ {
+ if (assemblySpec != null && !assemblySpec.Equals(""))
+ {
+ Append(", ");
+
+ if (_instNesting > 0)
+ {
+ EscapeEmbeddedAssemblyName(assemblySpec);
+ }
+ else
+ {
+ EscapeAssemblyName(assemblySpec);
+ }
+
+ _hasAssemblySpec = true;
+ }
+ }
+
+ public override string ToString()
+ {
+ Debug.Assert(_instNesting == 0);
+
+ return _str.ToString();
+ }
+
+ private static bool ContainsReservedChar(string name)
+ {
+ foreach (char c in name)
+ {
+ if (c == '\0')
+ break;
+ if (IsTypeNameReservedChar(c))
+ return true;
+ }
+ return false;
+ }
+
+ private static bool IsTypeNameReservedChar(char ch)
+ {
+ switch (ch)
+ {
+ case ',':
+ case '[':
+ case ']':
+ case '&':
+ case '*':
+ case '+':
+ case '\\':
+ return true;
+
+ default:
+ return false;
+ }
+ }
+
+ private void EscapeName(string name)
+ {
+ if (ContainsReservedChar(name))
+ {
+ foreach (char c in name)
+ {
+ if (c == '\0')
+ break;
+ if (IsTypeNameReservedChar(c))
+ _str.Append('\\');
+ _str.Append(c);
+ }
+ }
+ else
+ Append(name);
+ }
+
+ private void EscapeAssemblyName(string name)
+ {
+ Append(name);
+ }
+
+ private void EscapeEmbeddedAssemblyName(string name)
+ {
+ if (name.Contains(']'))
+ {
+ foreach (char c in name)
+ {
+ if (c == ']')
+ Append('\\');
+
+ Append(c);
+ }
+ }
+ else
+ {
+ Append(name);
+ }
+ }
+
+ private void PushOpenGenericArgument()
+ {
+ _stack.Add(_str.Length);
+ _stackIdx++;
+ }
+
+ private void PopOpenGenericArgument()
+ {
+ int index = _stack[--_stackIdx];
+ _stack.RemoveAt(_stackIdx);
+
+ if (!_hasAssemblySpec)
+ _str.Remove(index - 1, 1);
+
+ _hasAssemblySpec = false;
+ }
+
+ private void Append(string pStr)
+ {
+ int i = pStr.IndexOf('\0');
+ if (i < 0)
+ {
+ _str.Append(pStr);
+ }
+ else if (i > 0)
+ {
+ _str.Append(pStr.AsSpan(0, i));
+ }
+ }
+
+ private void Append(char c)
+ {
+ _str.Append(c);
+ }
+
+ internal enum Format
+ {
+ ToString,
+ FullName,
+ AssemblyQualifiedName,
+ }
+
+ internal static string? ToString(Type type, Format format)
+ {
+ if (format == Format.FullName || format == Format.AssemblyQualifiedName)
+ {
+ if (!type.IsGenericTypeDefinition && type.ContainsGenericParameters)
+ return null;
+ }
+
+ var tnb = new TypeNameBuilder();
+ tnb.AddAssemblyQualifiedName(type, format);
+ return tnb.ToString();
+ }
+
+ private void AddElementType(Type type)
+ {
+ if (!type.HasElementType)
+ return;
+
+ AddElementType(type.GetElementType()!);
+
+ if (type.IsPointer)
+ Append('*');
+ else if (type.IsByRef)
+ Append('&');
+ else if (type.IsSZArray)
+ Append("[]");
+ else if (type.IsArray)
+ AddArray(type.GetArrayRank());
+ }
+
+ private void AddAssemblyQualifiedName(Type type, Format format)
+ {
+ Type rootType = type;
+
+ while (rootType.HasElementType)
+ rootType = rootType.GetElementType()!;
+
+ // Append namespace + nesting + name
+ var nestings = new List();
+ for (Type? t = rootType; t != null; t = t.IsGenericParameter ? null : t.DeclaringType)
+ nestings.Add(t);
+
+ for (int i = nestings.Count - 1; i >= 0; i--)
+ {
+ Type enclosingType = nestings[i];
+ string name = enclosingType.Name;
+
+ if (i == nestings.Count - 1 && !string.IsNullOrEmpty(enclosingType.Namespace))
+ name = enclosingType.Namespace + "." + name;
+
+ AddName(name);
+ }
+
+ // Append generic arguments
+ if (rootType.IsGenericType && (!rootType.IsGenericTypeDefinition || format == Format.ToString))
+ {
+ Type[] genericArguments = rootType.GetGenericArguments();
+
+ OpenGenericArguments();
+ for (int i = 0; i < genericArguments.Length; i++)
+ {
+ Format genericArgumentsFormat = format == Format.FullName ? Format.AssemblyQualifiedName : format;
+
+ OpenGenericArgument();
+ AddAssemblyQualifiedName(genericArguments[i], genericArgumentsFormat);
+ CloseGenericArgument();
+ }
+ CloseGenericArguments();
+ }
+
+ // Append pointer, byRef and array qualifiers
+ AddElementType(type);
+
+ if (format == Format.AssemblyQualifiedName)
+ AddAssemblySpec(type.Module.Assembly.FullName!);
+ }
+ }
+}
diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs
index 79b9e77bfdf140..a43222afe34f05 100644
--- a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs
+++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveCustomAttributeTests.cs
@@ -21,9 +21,9 @@ public class AssemblySaveCustomAttributeTests
};
private static readonly Type s_comVisibleType = typeof(ComVisibleAttribute);
- private static readonly Type s_guideType = typeof(GuidAttribute);
+ private static readonly Type s_guidType = typeof(GuidAttribute);
private static readonly (ConstructorInfo con, object[] args) s_comVisiblePair = (s_comVisibleType.GetConstructor(new Type[] { typeof(bool) }), new object[] { true });
- private static readonly (ConstructorInfo con, object[] args) s_guidPair = (s_guideType.GetConstructor(new Type[] { typeof(string) }), new object[] { "9ED54F84-A89D-4fcd-A854-44251E925F09" });
+ private static readonly (ConstructorInfo con, object[] args) s_guidPair = (s_guidType.GetConstructor(new Type[] { typeof(string) }), new object[] { "9ED54F84-A89D-4fcd-A854-44251E925F09" });
private static AssemblyName PopulateAssemblyName()
{
@@ -42,10 +42,10 @@ public void AssemblyModuleWithCustomAttributes()
{
WriteAssemblyToDisk(assemblyName, Type.EmptyTypes, file.Path, _attributes, _attributes);
- Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
Module moduleFromDisk = assemblyFromDisk.Modules.First();
- AssemblyTools.AssertAssemblyNameAndModule(assemblyName, assemblyFromDisk.GetName(), moduleFromDisk);
+ AssemblySaveTools.AssertAssemblyNameAndModule(assemblyName, assemblyFromDisk.GetName(), moduleFromDisk);
ValidateAttributes(assemblyFromDisk.GetCustomAttributesData());
ValidateAttributes(moduleFromDisk.GetCustomAttributesData());
}
@@ -61,7 +61,7 @@ public void MethodFieldWithCustomAttributes()
WriteAssemblyToDisk(PopulateAssemblyName(), types, file.Path, typeAttributes: _attributes,
methodAttributes: _attributes, fieldAttributes: _attributes);
- Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
Module moduleFromDisk = assemblyFromDisk.Modules.First();
Type[] typesFromDisk = moduleFromDisk.GetTypes();
@@ -75,9 +75,9 @@ public void MethodFieldWithCustomAttributes()
MethodInfo[] methodsFromDisk = typeFromDisk.IsValueType ? typeFromDisk.GetMethods(BindingFlags.DeclaredOnly) : typeFromDisk.GetMethods();
FieldInfo[] fieldsFromDisk = typeFromDisk.GetFields();
- AssemblyTools.AssertTypeProperties(sourceType, typeFromDisk);
- AssemblyTools.AssertMethods(sourceType.IsValueType ? sourceType.GetMethods(BindingFlags.DeclaredOnly) : sourceType.GetMethods(), methodsFromDisk);
- AssemblyTools.AssertFields(sourceType.GetFields(), fieldsFromDisk);
+ AssemblySaveTools.AssertTypeProperties(sourceType, typeFromDisk);
+ AssemblySaveTools.AssertMethods(sourceType.IsValueType ? sourceType.GetMethods(BindingFlags.DeclaredOnly) : sourceType.GetMethods(), methodsFromDisk);
+ AssemblySaveTools.AssertFields(sourceType.GetFields(), fieldsFromDisk);
ValidateAttributes(typeFromDisk.GetCustomAttributesData());
for (int j = 0; j < methodsFromDisk.Length; j++)
@@ -109,7 +109,7 @@ private void ValidateAttributes(IList attributesFromDisk)
{
Assert.Equal(s_guidPair.con.MetadataToken, attribute.Constructor.MetadataToken);
Assert.Equal(s_guidPair.args[0].GetType().FullName, attribute.ConstructorArguments[0].ArgumentType.FullName);
- Assert.Equal(attribute.AttributeType.Name, s_guideType.Name);
+ Assert.Equal(attribute.AttributeType.Name, s_guidType.Name);
Assert.Equal(s_guidPair.args[0], attribute.ConstructorArguments[0].Value);
}
}
@@ -119,7 +119,7 @@ private static void WriteAssemblyToDisk(AssemblyName assemblyName, Type[] types,
List? moduleAttributes = null, List? typeAttributes = null,
List? methodAttributes = null, List? fieldAttributes = null)
{
- AssemblyBuilder assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(assemblyName, assemblyAttributes, typeof(string), out MethodInfo saveMethod);
+ AssemblyBuilder assemblyBuilder = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(assemblyName, assemblyAttributes, typeof(string), out MethodInfo saveMethod);
ModuleBuilder mb = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
PopulateMembersForModule(mb, types, moduleAttributes, typeAttributes, methodAttributes, fieldAttributes);
saveMethod.Invoke(assemblyBuilder, new object[] { fileLocation });
@@ -191,14 +191,14 @@ public void CreateStructWithPseudoCustomAttributesTest()
new CustomAttributeBuilder(typeof(SpecialNameAttribute).GetConstructor(Type.EmptyTypes), new object[] { })
};
- AssemblyBuilder ab = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
+ AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(
PopulateAssemblyName(), null, typeof(string), out MethodInfo saveMethod);
TypeBuilder tb = ab.DefineDynamicModule("Module").DefineType(type.FullName, type.Attributes, type.BaseType);
DefineFieldsAndSetAttributes(fieldAttributes.ToList(), type.GetFields(), tb);
typeAttributes.ForEach(tb.SetCustomAttribute);
saveMethod.Invoke(ab, new object[] { file.Path });
- Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
Module moduleFromDisk = assemblyFromDisk.Modules.First();
Type testType = moduleFromDisk.GetTypes()[0];
IList attributesFromDisk = testType.GetCustomAttributesData();
@@ -280,13 +280,13 @@ public void InterfacesWithPseudoCustomAttributes()
new CustomAttributeBuilder(marshalAsEnumCtor, new object[] { UnmanagedType.CustomMarshaler },
new FieldInfo[] { typeof(MarshalAsAttribute).GetField("MarshalType")}, new object[] { typeof(EmptyTestClass).AssemblyQualifiedName })};
- AssemblyBuilder ab = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(PopulateAssemblyName(), null, typeof(string), out MethodInfo saveMethod);
+ AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(PopulateAssemblyName(), null, typeof(string), out MethodInfo saveMethod);
TypeBuilder tb = ab.DefineDynamicModule("Module").DefineType(type.FullName, type.Attributes);
typeAttributes.ForEach(tb.SetCustomAttribute);
DefineMethodsAndSetAttributes(methodAttributes, tb, type.GetMethods(), parameterAttributes);
saveMethod.Invoke(ab, new object[] { file.Path });
- Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
Type testType = assemblyFromDisk.Modules.First().GetTypes()[0];
IList attributesFromDisk = testType.GetCustomAttributesData();
@@ -429,7 +429,7 @@ public void MarshalAsPseudoCustomAttributesTest(CustomAttributeBuilder attribute
using (TempFile file = TempFile.Create())
{
Type type = typeof(StructWithFields);
- AssemblyBuilder ab = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
+ AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(
PopulateAssemblyName(), null, typeof(string), out MethodInfo saveMethod);
TypeBuilder tb = ab.DefineDynamicModule("Module").DefineType(type.FullName, type.Attributes, type.BaseType);
FieldInfo stringField = type.GetFields()[1];
@@ -437,7 +437,7 @@ public void MarshalAsPseudoCustomAttributesTest(CustomAttributeBuilder attribute
fb.SetCustomAttribute(attribute);
saveMethod.Invoke(ab, new object[] { file.Path });
- Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
FieldInfo field = assemblyFromDisk.Modules.First().GetTypes()[0].GetFields()[0];
CustomAttributeData attributeFromDisk = field.GetCustomAttributesData()[0];
@@ -458,5 +458,51 @@ public void MarshalAsPseudoCustomAttributesTest(CustomAttributeBuilder attribute
}
}
}
+
+ [Fact]
+ public void EnumBuilderSetCustomAttributesTest()
+ {
+ using (TempFile file = TempFile.Create())
+ {
+ AssemblyBuilder ab = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(
+ PopulateAssemblyName(), null, typeof(string), out MethodInfo saveMethod);
+ EnumBuilder enumBuilder = ab.DefineDynamicModule("Module").DefineEnum("TestEnum", TypeAttributes.Public, typeof(int));
+
+ ConstructorInfo attributeConstructor = typeof(BoolAttribute).GetConstructor(new Type[] { typeof(bool) });
+ CustomAttributeBuilder attributeBuilder = new CustomAttributeBuilder(attributeConstructor, new object[] { true });
+ enumBuilder.SetCustomAttribute(attributeBuilder);
+ enumBuilder.SetCustomAttribute(new CustomAttributeBuilder(s_guidPair.con, s_guidPair.args));
+ saveMethod.Invoke(ab, new object[] { file.Path });
+
+ Type testEnum = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestEnum");
+
+ Assert.True(testEnum.IsEnum);
+ AssemblySaveTools.AssertTypeProperties(enumBuilder, testEnum);
+
+ CustomAttributeData[] attributes = testEnum.GetCustomAttributesData().ToArray();
+ if (attributes[0].AttributeType.Name == s_guidType.Name)
+ {
+ AssertEnumAttributes(s_guidType.FullName, "9ED54F84-A89D-4fcd-A854-44251E925F09", attributes[0]);
+ AssertEnumAttributes(typeof(BoolAttribute).FullName, true, attributes[1]);
+ }
+ else
+ {
+ AssertEnumAttributes(s_guidType.FullName, "9ED54F84-A89D-4fcd-A854-44251E925F09", attributes[1]);
+ AssertEnumAttributes(typeof(BoolAttribute).FullName, true, attributes[0]);
+ }
+
+ }
+ }
+ private void AssertEnumAttributes(string fullName, object value, CustomAttributeData testAttrbiute)
+ {
+ Assert.Equal(fullName, testAttrbiute.AttributeType.FullName);
+ Assert.Equal(value, testAttrbiute.ConstructorArguments[0].Value);
+ }
+ }
+
+ public class BoolAttribute : Attribute
+ {
+ private bool _b;
+ public BoolAttribute(bool myBool) { _b = myBool; }
}
}
diff --git a/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveEnumBuilderTests.cs b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveEnumBuilderTests.cs
new file mode 100644
index 00000000000000..0fddcb4f54b98c
--- /dev/null
+++ b/src/libraries/System.Reflection.Emit/tests/PersistableAssemblyBuilder/AssemblySaveEnumBuilderTests.cs
@@ -0,0 +1,182 @@
+// 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.IO;
+using System.Linq;
+using Xunit;
+
+namespace System.Reflection.Emit.Tests
+{
+ [ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
+ public class AssemblySaveEnumBuilderTests
+ {
+ private static AssemblyName PopulateAssemblyName()
+ {
+ AssemblyName assemblyName = new AssemblyName("MyDynamicAssembly");
+ assemblyName.Version = new Version("7.0.0.0");
+ assemblyName.CultureInfo = Globalization.CultureInfo.InvariantCulture;
+ return assemblyName;
+ }
+
+ public static IEnumerable