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",
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)!;
+ }
}
}
-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}"
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {739AA767-154B-4C69-8C9B-C3D332833D92}
EndGlobalSection
-EndGlobal
+EndGlobal
\ No newline at end of file
<data name="InvalidOperation_GenericParametersAlreadySet" xml:space="preserve">
<value>The generic parameters are already defined on this MethodBuilder.</value>
</data>
+ <data name="Argument_ShouldOnlySetVisibilityFlags" xml:space="preserve">
+ <value>Should only set visibility flags when creating EnumBuilder.</value>
+ </data>
+ <data name="Argument_ConstantDoesntMatch" xml:space="preserve">
+ <value>Constant does not match the defined type.</value>
+ </data>
+ <data name="Argument_ConstantNull" xml:space="preserve">
+ <value>Null is not a valid constant value for this type.</value>
+ </data>
+ <data name="InvalidOperation_NoUnderlyingTypeOnEnum" xml:space="preserve">
+ <value>Underlying type information on enumeration is not specified.</value>
+ </data>
</root>
\ No newline at end of file
<ItemGroup>
<Compile Include="System\Reflection\Emit\CustomAttributeWrapper.cs" />
<Compile Include="System\Reflection\Emit\AssemblyBuilderImpl.cs" />
+ <Compile Include="System\Reflection\Emit\EnumBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\FieldBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\GenericTypeParameterBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\MethodBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\ModuleBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\ParameterBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\PseudoCustomAttributesData.cs" />
- <Compile Include="System\Reflection\Emit\TypeBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\SignatureHelper.cs" />
+ <Compile Include="System\Reflection\Emit\TypeBuilderImpl.cs" />
+ <Compile Include="System\Reflection\Emit\TypeNameBuilder.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="$(CoreLibProject)" />
--- /dev/null
+// 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<byte> 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();
+ }
+}
internal MarshallingData? _marshallingData;
internal int _offset;
internal List<CustomAttributeWrapper>? _customAttributes;
+ internal object? _defaultValue = DBNull.Value;
internal FieldBuilderImpl(TypeBuilderImpl typeBuilder, string fieldName, Type type, FieldAttributes attributes)
{
_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<byte> binaryAttribute)
{
// Handle pseudo custom attributes
{
AddMarshalling(fieldHandle, field._marshallingData.SerializeMarshallingData());
}
+
+ if (field._defaultValue != DBNull.Value)
+ {
+ AddDefaultValue(fieldHandle, field._defaultValue);
+ }
}
}
}
}
- 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(
return tb._handle;
}
+ if (type is EnumBuilderImpl eb && Equals(eb.Module))
+ {
+ return eb._typeBuilder._handle;
+ }
+
return GetTypeReference(type);
}
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)
{
_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<byte> binaryAttribute)
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;
private TypeAttributes _attributes;
private PackingSize _packingSize;
private int _typeSize;
+ private Type? _enumUnderlyingType;
internal readonly TypeDefinitionHandle _handle;
internal readonly List<MethodBuilderImpl> _methodDefinitions = new();
_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;
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
+ internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
+ {
+ SetCustomAttributeCore(con, binaryAttribute);
+ }
+
private void ParseStructLayoutAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
CustomAttributeInfo attributeInfo = CustomAttributeInfo.DecodeCustomAttribute(con, binaryAttribute);
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);
--- /dev/null
+// 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<int> _stack = new List<int>();
+ 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<Type>();
+ 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!);
+ }
+ }
+}
};
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()
{
{
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());
}
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();
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++)
{
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);
}
}
List<CustomAttributeBuilder>? moduleAttributes = null, List<CustomAttributeBuilder>? typeAttributes = null,
List<CustomAttributeBuilder>? methodAttributes = null, List<CustomAttributeBuilder>? 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 });
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<CustomAttributeData> attributesFromDisk = testType.GetCustomAttributesData();
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<CustomAttributeData> attributesFromDisk = testType.GetCustomAttributesData();
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];
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];
}
}
}
+
+ [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; }
}
}
--- /dev/null
+// 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<object[]> DefineLiteral_TestData()
+ {
+ yield return new object[] { typeof(byte), (byte)0 };
+ yield return new object[] { typeof(byte), (byte)1 };
+
+ yield return new object[] { typeof(sbyte), (sbyte)0 };
+ yield return new object[] { typeof(sbyte), (sbyte)1 };
+
+ yield return new object[] { typeof(ushort), (ushort)0 };
+ yield return new object[] { typeof(ushort), (ushort)1 };
+
+ yield return new object[] { typeof(short), (short)0 };
+ yield return new object[] { typeof(short), (short)1 };
+
+ yield return new object[] { typeof(uint), (uint)0 };
+ 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(ulong), (ulong)0 };
+ yield return new object[] { typeof(ulong), (ulong)1 };
+
+ yield return new object[] { typeof(long), (long)0 };
+ yield return new object[] { typeof(long), (long)1 };
+
+ yield return new object[] { typeof(char), (char)0 };
+ yield return new object[] { typeof(char), (char)1 };
+
+ yield return new object[] { typeof(bool), true };
+ yield return new object[] { typeof(bool), false };
+
+ yield return new object[] { typeof(float), 0f };
+ yield return new object[] { typeof(float), 1.1f };
+
+ yield return new object[] { typeof(double), 0d };
+ yield return new object[] { typeof(double), 1.1d };
+ }
+
+ [Theory]
+ [MemberData(nameof(DefineLiteral_TestData))]
+ public void DefineLiteral(Type underlyingType, object literalValue)
+ {
+ using (TempFile file = TempFile.Create())
+ {
+ EnumBuilder enumBuilder = CreateAssemblyAndDefineEnum(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod, out TypeBuilder _, underlyingType);
+ FieldBuilder literal = enumBuilder.DefineLiteral("FieldOne", literalValue);
+ saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
+ Module moduleFromDisk = assemblyFromDisk.Modules.First();
+ Type testEnum = moduleFromDisk.GetType("TestEnum");
+
+ Assert.True(testEnum.IsEnum);
+ AssemblySaveTools.AssertTypeProperties(enumBuilder, testEnum);
+ Assert.Equal(underlyingType.FullName, testEnum.GetEnumUnderlyingType().FullName);
+
+ FieldInfo testField = testEnum.GetField("FieldOne");
+ Assert.Equal(enumBuilder.Name, testField.DeclaringType.Name);
+ Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal, literal.Attributes);
+ Assert.Equal(enumBuilder.AsType().FullName, testField.FieldType.FullName);
+ }
+ }
+
+ [Theory]
+ [InlineData(0, "TestEnum[]")]
+ [InlineData(1, "TestEnum[]")]
+ [InlineData(2, "TestEnum[,]")]
+ [InlineData(3, "TestEnum[,,]")]
+ public void SaveArrayTypeSignature(int rank, string name)
+ {
+ using (TempFile file = TempFile.Create())
+ {
+ EnumBuilder enumBuilder = CreateAssemblyAndDefineEnum(out AssemblyBuilder ab, out MethodInfo saveMethod, out TypeBuilder tb);
+ Type arrayType = rank == 0 ? enumBuilder.MakeArrayType() : enumBuilder.MakeArrayType(rank);
+ MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+ mb.SetReturnType(arrayType);
+ mb.SetParameters(new Type[] { typeof(INoMethod), arrayType });
+ saveMethod.Invoke(ab, new object[] { file.Path });
+
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestInterface");
+ MethodInfo testMethod = testType.GetMethod("TestMethod");
+
+ AssertArrayTypeSignature(rank, name, testMethod.ReturnType);
+ AssertArrayTypeSignature(rank, name, testMethod.GetParameters()[1].ParameterType);
+ }
+ }
+
+ private EnumBuilder CreateAssemblyAndDefineEnum(out AssemblyBuilder assemblyBuilder,
+ out MethodInfo saveMethod, out TypeBuilder type, Type? underlyingType = null)
+ {
+ assemblyBuilder = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(
+ PopulateAssemblyName(), null, typeof(string), out saveMethod);
+ ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module");
+ type = mb.DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract);
+ return mb.DefineEnum("TestEnum", TypeAttributes.Public, underlyingType == null ? typeof(int) : underlyingType);
+ }
+
+ private static void AssertArrayTypeSignature(int rank, string name, Type arrayType)
+ {
+ Assert.True(rank < 2 ? arrayType.IsSZArray : arrayType.IsArray);
+ rank = rank == 0 ? rank + 1 : rank;
+ Assert.Equal(rank, arrayType.GetArrayRank());
+ Assert.Equal(name, arrayType.Name);
+ }
+
+ [Fact]
+ public void SaveByRefTypeSignature()
+ {
+ using (TempFile file = TempFile.Create())
+ {
+ EnumBuilder eb = CreateAssemblyAndDefineEnum(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod, out TypeBuilder tb);
+ Type byrefType = eb.MakeByRefType();
+ MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+ mb.SetReturnType(byrefType);
+ mb.SetParameters(new Type[] { typeof(INoMethod), byrefType });
+ saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestInterface");
+ MethodInfo testMethod = testType.GetMethod("TestMethod");
+
+ Assert.False(testMethod.GetParameters()[0].ParameterType.IsByRef);
+ AssertByRefType(testMethod.GetParameters()[1].ParameterType);
+ AssertByRefType(testMethod.ReturnType);
+ }
+ }
+
+ private static void AssertByRefType(Type byrefParam)
+ {
+ Assert.True(byrefParam.IsByRef);
+ Assert.Equal("TestEnum&", byrefParam.Name);
+ }
+
+ [Fact]
+ public void SavePointerTypeSignature()
+ {
+ using (TempFile file = TempFile.Create())
+ {
+ EnumBuilder eb = CreateAssemblyAndDefineEnum(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod, out TypeBuilder tb);
+ Type pointerType = eb.MakePointerType();
+ MethodBuilder mb = tb.DefineMethod("TestMethod", MethodAttributes.Public);
+ mb.SetReturnType(pointerType);
+ mb.SetParameters(new Type[] { typeof(INoMethod), pointerType });
+ saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
+
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetType("TestInterface");
+ MethodInfo testMethod = testType.GetMethod("TestMethod");
+
+ Assert.False(testMethod.GetParameters()[0].ParameterType.IsPointer);
+ AssertPointerType(testMethod.GetParameters()[1].ParameterType);
+ AssertPointerType(testMethod.ReturnType);
+ }
+ }
+
+ private void AssertPointerType(Type testType)
+ {
+ Assert.True(testType.IsPointer);
+ Assert.Equal("TestEnum*", testType.Name);
+ }
+ }
+}
namespace System.Reflection.Emit.Tests
{
- internal static class AssemblyTools
+ internal static class AssemblySaveTools
{
internal static void WriteAssemblyToDisk(AssemblyName assemblyName, Type[] types, string fileLocation)
{
internal sealed class CoreMetadataAssemblyResolver : MetadataAssemblyResolver
{
public static Assembly s_coreAssembly = typeof(object).Assembly;
- public static Assembly s_emitAssembly = typeof(AssemblyTools).Assembly;
+ public static Assembly s_emitAssembly = typeof(AssemblySaveTools).Assembly;
public CoreMetadataAssemblyResolver() { }
public override Assembly Resolve(MetadataLoadContext context, AssemblyName assemblyName)
namespace System.Reflection.Emit.Tests
{
[ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
- public class AssemblySaveWithVariousMembersTests
+ public class AssemblySaveTypeBuilderTests
{
private static readonly AssemblyName s_assemblyName = new AssemblyName("MyDynamicAssembly")
{
Assembly assemblyFromDisk = WriteAndLoadAssembly(Type.EmptyTypes, file.Path);
Assert.Empty(assemblyFromDisk.GetTypes());
- AssemblyTools.AssertAssemblyNameAndModule(s_assemblyName, assemblyFromDisk.GetName(), assemblyFromDisk.Modules.FirstOrDefault());
+ AssemblySaveTools.AssertAssemblyNameAndModule(s_assemblyName, assemblyFromDisk.GetName(), assemblyFromDisk.Modules.FirstOrDefault());
}
}
private static Assembly WriteAndLoadAssembly(Type[] types, string filePath)
{
- AssemblyTools.WriteAssemblyToDisk(s_assemblyName, types, filePath);
+ AssemblySaveTools.WriteAssemblyToDisk(s_assemblyName, types, filePath);
- return AssemblyTools.LoadAssemblyFromPath(filePath);
+ return AssemblySaveTools.LoadAssemblyFromPath(filePath);
}
public static IEnumerable<object[]> VariousInterfacesStructsTestData()
Type sourceType = types[i];
Type typeFromDisk = typesFromDisk[i];
- AssemblyTools.AssertTypeProperties(sourceType, typeFromDisk);
- AssemblyTools.AssertMethods(sourceType.GetMethods(), typeFromDisk.GetMethods());
- AssemblyTools.AssertFields(sourceType.GetFields(), typeFromDisk.GetFields());
+ AssemblySaveTools.AssertTypeProperties(sourceType, typeFromDisk);
+ AssemblySaveTools.AssertMethods(sourceType.GetMethods(), typeFromDisk.GetMethods());
+ AssemblySaveTools.AssertFields(sourceType.GetFields(), typeFromDisk.GetFields());
}
}
{
using (var stream = new MemoryStream())
{
- AssemblyTools.WriteAssemblyToStream(s_assemblyName, types, stream);
- Assembly assemblyFromStream = AssemblyTools.LoadAssemblyFromStream(stream);
+ AssemblySaveTools.WriteAssemblyToStream(s_assemblyName, types, stream);
+ Assembly assemblyFromStream = AssemblySaveTools.LoadAssemblyFromStream(stream);
AssertTypesAndTypeMembers(types, assemblyFromStream.Modules.First().GetTypes());
}
tb.DefineMethod("TestMethod", MethodAttributes.Public);
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
Module moduleFromDisk = assemblyFromDisk.Modules.First();
Assert.Equal("MyModule", moduleFromDisk.ScopeName);
private static TypeBuilder CreateAssemblyAndDefineType(out AssemblyBuilder assemblyBuilder, out MethodInfo saveMethod)
{
- assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(s_assemblyName, null, typeof(string), out saveMethod);
+ assemblyBuilder = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(s_assemblyName, null, typeof(string), out saveMethod);
return assemblyBuilder.DefineDynamicModule("MyModule")
.DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract);
}
{
using (TempFile file = TempFile.Create())
{
- AssemblyBuilder assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
+ AssemblyBuilder assemblyBuilder = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(
s_assemblyName, null, typeof(string), out MethodInfo saveMethod);
ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module");
TypeBuilder tb = mb.DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract, null, new Type[] { typeof(IOneMethod)});
tb.DefineNestedType("NestedType", TypeAttributes.Interface | TypeAttributes.Abstract);
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
+ Assembly assemblyFromDisk = AssemblySaveTools.LoadAssemblyFromPath(file.Path);
Type testType = assemblyFromDisk.Modules.First().GetTypes()[0];
Type[] interfaces = testType.GetInterfaces();
}
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
MethodInfo testMethod = testType.GetMethod("TestMethod");
Type[] genericTypeParams = testType.GetGenericArguments();
}
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
MethodInfo testMethod = testType.GetMethod("TestMethod");
Type[] genericTypeParams = testMethod.GetGenericArguments();
mb.SetParameters(new Type[] { typeof(INoMethod), arrayType, typeof(int[,,,]) });
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
MethodInfo testMethod = testType.GetMethod("TestMethod");
Type intArray = testMethod.GetParameters()[2].ParameterType;
mb.SetParameters(new Type[] { typeof(INoMethod), byrefType });
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
MethodInfo testMethod = testType.GetMethod("TestMethod");
Assert.False(testMethod.GetParameters()[0].ParameterType.IsByRef);
mb.SetParameters(new Type[] { typeof(INoMethod), pointerType });
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
MethodInfo testMethod = testType.GetMethod("TestMethod");
Assert.False(testMethod.GetParameters()[0].ParameterType.IsPointer);
mb.SetParameters(new Type[] { typeof(INoMethod), genericType });
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
MethodInfo testMethod = testType.GetMethod("TestMethod");
Type paramType = testMethod.GetParameters()[1].ParameterType;
mb.SetParameters(new Type[] { typeof(INoMethod), genericType, typeParams[1] });
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Type testType = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
+ Type testType = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First().GetTypes()[0];
MethodInfo testMethod = testType.GetMethod("TestMethod");
Type paramType = testMethod.GetParameters()[1].ParameterType;
Type genericParameter = testMethod.GetParameters()[2].ParameterType;
{
using (TempFile file = TempFile.Create())
{
- AssemblyBuilder assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
+ AssemblyBuilder assemblyBuilder = AssemblySaveTools.PopulateAssemblyBuilderAndSaveMethod(
s_assemblyName, null, typeof(string), out MethodInfo saveMethod);
ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module");
TypeBuilder tb = mb.DefineType("TestInterface1", TypeAttributes.Interface | TypeAttributes.Abstract);
typePar[0].SetBaseTypeConstraint(typeof(EmptyTestClass));
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });
- Module m = AssemblyTools.LoadAssemblyFromPath(file.Path).Modules.First();
+ Module m = AssemblySaveTools.LoadAssemblyFromPath(file.Path).Modules.First();
Type[] type1Params = m.GetTypes()[0].GetGenericArguments();
Type[] type2Params = m.GetTypes()[1].GetGenericArguments();
Type[] type3Params = m.GetTypes()[2].GetGenericArguments();
<Compile Include="ModuleBuilder\ModuleBuilderSetCustomAttribute.cs" />
<Compile Include="ParameterBuilder\ParameterBuilderSetConstant.cs" />
<Compile Include="PersistableAssemblyBuilder\AssemblySaveCustomAttributeTests.cs" />
- <Compile Include="PersistableAssemblyBuilder\AssemblySaveWithVariousMembersTests.cs" />
- <Compile Include="PersistableAssemblyBuilder\AssemblyTools.cs" />
+ <Compile Include="PersistableAssemblyBuilder\AssemblySaveEnumBuilderTests.cs" />
+ <Compile Include="PersistableAssemblyBuilder\AssemblySaveTools.cs" />
+ <Compile Include="PersistableAssemblyBuilder\AssemblySaveTypeBuilderTests.cs" />
<Compile Include="PropertyBuilder\PropertyBuilderAddOtherMethod.cs" />
<Compile Include="PropertyBuilder\PropertyBuilderAttributes.cs" />
<Compile Include="PropertyBuilder\PropertyBuilderCanRead.cs" />
return _tb.IsDefined(attributeType, inherit);
}
- [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)!;
- }
-
- public override Type MakeByRefType()
- {
- return SymbolType.FormCompoundType("&", this, 0)!;
- }
-
- public override Type MakePointerType()
- {
- return SymbolType.FormCompoundType("*", this, 0)!;
- }
-
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
_tb.SetCustomAttribute(con, binaryAttribute);