未验证 提交 2a75e65f 编写于 作者: B Buyaa Namnan 提交者: GitHub

AssemblyBuilder.Save add custom attributes handling. (#84580)

* Initial custom attributes handling

* Pseudo custom attributes handling and tests

* Use ReadOnlySpan for CustomAttribute binaryData

* Update some pseudo attributes handling and apply feedback

* Add one more pseudo attribute and a few small changes

* Move pseudo attributes handling

* Remove type loading logic from CustomAttributes parsing, use constants for some values

* Add MarshalAsAttribute handling and apply other feedbacks

---------
Co-authored-by: NAaron Robinson <arobins@microsoft.com>
上级 184d17dc
......@@ -21,10 +21,14 @@ namespace System.Reflection.Emit
{
public class CustomAttributeBuilder
{
internal readonly ConstructorInfo m_con;
private readonly ConstructorInfo m_con;
private readonly object?[] m_constructorArgs;
private readonly byte[] m_blob;
internal ConstructorInfo Ctor => m_con;
internal byte[] Data => m_blob;
// public constructor to form the custom attribute with constructor and constructor
// parameters.
public CustomAttributeBuilder(ConstructorInfo con, object?[] constructorArgs) :
......
......@@ -288,7 +288,7 @@ internal void CheckTypeNameConflict(string strTypeName, TypeBuilder? enclosingTy
/// <summary>
/// Use this function if client decides to form the custom attribute blob themselves.
/// </summary>
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
lock (SyncRoot)
{
......@@ -299,16 +299,5 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binar
binaryAttribute);
}
}
/// <summary>
/// Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder.
/// </summary>
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
lock (SyncRoot)
{
customBuilder.CreateCustomAttribute(_manifestModuleBuilder, AssemblyDefToken);
}
}
}
}
......@@ -157,16 +157,11 @@ internal override Type GetReturnType()
return m_methodBuilder.ReturnType;
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
m_methodBuilder.SetCustomAttribute(con, binaryAttribute);
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
m_methodBuilder.SetCustomAttribute(customBuilder);
}
protected override void SetImplementationFlagsCore(MethodImplAttributes attributes)
{
m_methodBuilder.SetImplementationFlags(attributes);
......
......@@ -274,18 +274,11 @@ public override object[] GetCustomAttributes(Type attributeType, bool inherit)
}
// Use this function if client decides to form the custom attribute blob themselves
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
m_typeBuilder.SetCustomAttribute(con, binaryAttribute);
}
// Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
m_typeBuilder.SetCustomAttribute(customBuilder);
}
// Return the class that declared this Field.
public override Type? DeclaringType => m_typeBuilder.DeclaringType;
......@@ -293,7 +286,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
public override Type? ReflectedType => m_typeBuilder.ReflectedType;
// Returns true if one or more instance of attributeType is defined on this member.
public override bool IsDefined(Type attributeType, bool inherit)
{
......@@ -329,7 +321,6 @@ public override Type MakeArrayType(int 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",
......
......@@ -80,7 +80,7 @@ protected override void AddOtherMethodCore(MethodBuilder mdBuilder)
// Use this function if client decides to form the custom attribute blob themselves
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
m_type.ThrowIfCreated();
......@@ -91,13 +91,6 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binar
binaryAttribute);
}
// Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
m_type.ThrowIfCreated();
customBuilder.CreateCustomAttribute(m_module, m_evToken);
}
private readonly string m_name; // The name of the event
private readonly int m_evToken; // The token of this event
private readonly RuntimeModuleBuilder m_module;
......
......@@ -150,7 +150,7 @@ protected override void SetConstantCore(object? defaultValue)
RuntimeTypeBuilder.SetConstantValue(m_typeBuilder.GetModuleBuilder(), m_fieldTok, m_fieldType, defaultValue);
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
RuntimeModuleBuilder moduleBuilder = (RuntimeModuleBuilder)m_typeBuilder.Module;
......@@ -160,13 +160,6 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binar
m_fieldTok, moduleBuilder.GetMethodMetadataToken(con), binaryAttribute);
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
m_typeBuilder.ThrowIfCreated();
customBuilder.CreateCustomAttribute((RuntimeModuleBuilder)m_typeBuilder.Module, m_fieldTok);
}
#endregion
}
}
......@@ -215,16 +215,11 @@ public override Type MakeArrayType(int rank)
#endregion
#region Protected Members Overrides
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
m_type.SetGenParamCustomAttribute(con, binaryAttribute);
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
m_type.SetGenParamCustomAttribute(customBuilder);
}
protected override void SetBaseTypeConstraintCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? baseTypeConstraint)
{
m_type.SetParent(baseTypeConstraint);
......
......@@ -695,7 +695,7 @@ internal Module GetModule()
return GetModuleBuilder();
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
ThrowIfGeneric();
RuntimeTypeBuilder.DefineCustomAttribute(m_module, MetadataToken,
......@@ -706,15 +706,6 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binar
ParseCA(con);
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
ThrowIfGeneric();
customBuilder.CreateCustomAttribute(m_module, MetadataToken);
if (IsKnownCA(customBuilder.m_con))
ParseCA(customBuilder.m_con);
}
// this method should return true for any and every ca that requires more work
// than just setting the ca
private static bool IsKnownCA(ConstructorInfo con)
......
......@@ -1289,7 +1289,7 @@ internal int GetSignatureToken(byte[] sigBytes, int sigLength)
#region Other
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
RuntimeTypeBuilder.DefineCustomAttribute(
this,
......@@ -1298,11 +1298,6 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binar
binaryAttribute);
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
customBuilder.CreateCustomAttribute(this, 1); // This is hard coding the module token to 1
}
#endregion
#endregion
......
......@@ -97,8 +97,7 @@ protected override void AddOtherMethodCore(MethodBuilder mdBuilder)
}
// Use this function if client decides to form the custom attribute blob themselves
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
m_containingType.ThrowIfCreated();
RuntimeTypeBuilder.DefineCustomAttribute(
......@@ -108,13 +107,6 @@ protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binar
binaryAttribute);
}
// Use this function if client wishes to build CustomAttribute using CustomAttributeBuilder
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
{
m_containingType.ThrowIfCreated();
customBuilder.CreateCustomAttribute(m_moduleBuilder, m_tkProperty);
}
// Not supported functions in dynamic module.
public override object GetValue(object? obj, object?[]? index)
{
......
......@@ -111,13 +111,12 @@ private sealed class CustAttr
private readonly byte[]? m_binaryAttribute;
private readonly CustomAttributeBuilder? m_customBuilder;
public CustAttr(ConstructorInfo con, byte[] binaryAttribute)
public CustAttr(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
ArgumentNullException.ThrowIfNull(con);
ArgumentNullException.ThrowIfNull(binaryAttribute);
m_con = con;
m_binaryAttribute = binaryAttribute;
m_binaryAttribute = binaryAttribute.ToArray();
}
public CustAttr(CustomAttributeBuilder customBuilder)
......@@ -173,21 +172,13 @@ public void Bake(RuntimeModuleBuilder module, int token)
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineCustomAttribute")]
private static partial void DefineCustomAttribute(QCallModule module, int tkAssociate, int tkConstructor,
byte[]? attr, int attrLength);
ReadOnlySpan<byte> attr, int attrLength);
internal static void DefineCustomAttribute(RuntimeModuleBuilder module, int tkAssociate, int tkConstructor,
byte[]? attr)
ReadOnlySpan<byte> attr)
{
byte[]? localAttr = null;
if (attr != null)
{
localAttr = new byte[attr.Length];
Buffer.BlockCopy(attr, 0, localAttr, 0, attr.Length);
}
DefineCustomAttribute(new QCallModule(ref module), tkAssociate, tkConstructor,
localAttr, (localAttr != null) ? localAttr.Length : 0);
attr, attr.Length);
}
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "TypeBuilder_DefineProperty", StringMarshalling = StringMarshalling.Utf16)]
......@@ -670,7 +661,7 @@ internal void SetGenParamAttributes(GenericParameterAttributes genericParameterA
m_genParamAttributes = genericParameterAttributes;
}
internal void SetGenParamCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
internal void SetGenParamCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
CustAttr ca = new CustAttr(con, binaryAttribute);
......@@ -1858,14 +1849,14 @@ internal int TypeToken
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
DefineCustomAttribute(m_module, m_tdType, m_module.GetMethodMetadataToken(con), binaryAttribute);
SetCustomAttributeCore(con, binaryAttribute);
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
customBuilder.CreateCustomAttribute(m_module, m_tdType);
DefineCustomAttribute(m_module, m_tdType, m_module.GetMethodMetadataToken(con), binaryAttribute);
}
#endregion
......
......@@ -24,5 +24,10 @@ public CustomAttributeBuilder(ConstructorInfo con, object[] constructorArgs, Pro
{
ReflectionEmitThrower.ThrowPlatformNotSupportedException();
}
#pragma warning disable CA1822 // Member 'Ctor' does not access instance data and can be marked as static
internal ConstructorInfo Ctor => default;
internal byte[] Data => default;
#pragma warning restore CA1822
}
}
......@@ -39,17 +39,15 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
[System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")]
[RequiresAssemblyFiles(ThrowingMessageInRAF)]
public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly);
......
......@@ -31,14 +31,21 @@ public ILGenerator GetILGenerator(int streamSize)
protected abstract ILGenerator GetILGeneratorCore(int streamSize);
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
=> SetCustomAttributeCore(con, binaryAttribute);
{
ArgumentNullException.ThrowIfNull(con);
ArgumentNullException.ThrowIfNull(binaryAttribute);
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
=> SetCustomAttributeCore(customBuilder);
{
ArgumentNullException.ThrowIfNull(customBuilder);
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
public void SetImplementationFlags(MethodImplAttributes attributes)
=> SetImplementationFlagsCore(attributes);
......
......@@ -35,11 +35,9 @@ public FieldBuilder DefineLiteral(string literalName, object? literalValue)
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
=> SetCustomAttributeCore(con, binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
=> SetCustomAttributeCore(customBuilder);
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
=> SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
}
......@@ -27,17 +27,15 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
public void SetRaiseMethod(MethodBuilder mdBuilder)
=> SetRaiseMethodCore(mdBuilder);
......
......@@ -22,17 +22,15 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
public void SetOffset(int iOffset)
=> SetOffsetCore(iOffset);
......
......@@ -13,17 +13,15 @@ protected GenericTypeParameterBuilder()
public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute) => SetCustomAttributeCore(con, binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
public void SetBaseTypeConstraint([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? baseTypeConstraint) => SetBaseTypeConstraintCore(baseTypeConstraint);
protected abstract void SetBaseTypeConstraintCore([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? baseTypeConstraint);
......
......@@ -56,17 +56,20 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
public void SetImplementationFlags(MethodImplAttributes attributes) => SetImplementationFlagsCore(attributes);
protected abstract void SetImplementationFlagsCore(MethodImplAttributes attributes);
......
......@@ -134,17 +134,15 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
public abstract int GetTypeMetadataToken(Type type);
public abstract int GetFieldMetadataToken(FieldInfo field);
public abstract int GetMethodMetadataToken(MethodInfo method);
......
......@@ -27,15 +27,14 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
public void SetGetMethod(MethodBuilder mdBuilder)
=> SetGetMethodCore(mdBuilder);
......
......@@ -277,17 +277,15 @@ public void SetCustomAttribute(ConstructorInfo con, byte[] binaryAttribute)
SetCustomAttributeCore(con, binaryAttribute);
}
protected abstract void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute);
protected abstract void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute);
public void SetCustomAttribute(CustomAttributeBuilder customBuilder)
{
ArgumentNullException.ThrowIfNull(customBuilder);
SetCustomAttributeCore(customBuilder);
SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data);
}
protected abstract void SetCustomAttributeCore(CustomAttributeBuilder customBuilder);
public void SetParent([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent)
=> SetParentCore(parent);
......
......@@ -55,9 +55,8 @@ public abstract partial class AssemblyBuilder : System.Reflection.Assembly
public override System.Type? GetType(string name, bool throwOnError, bool ignoreCase) { throw null; }
public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
}
[System.FlagsAttribute]
public enum AssemblyBuilderAccess
......@@ -91,9 +90,8 @@ public abstract partial class ConstructorBuilder : System.Reflection.Constructor
public override object Invoke(System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder? binder, object?[]? parameters, System.Globalization.CultureInfo? culture) { throw null; }
public override bool IsDefined(System.Type attributeType, bool inherit) { throw null; }
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
public void SetImplementationFlags(System.Reflection.MethodImplAttributes attributes) { }
protected abstract void SetImplementationFlagsCore(System.Reflection.MethodImplAttributes attributes);
public override string ToString() { throw null; }
......@@ -186,9 +184,8 @@ public abstract partial class EnumBuilder : System.Reflection.TypeInfo
public override System.Type MakeByRefType() { throw null; }
public override System.Type MakePointerType() { throw null; }
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
}
public abstract partial class EventBuilder
{
......@@ -198,9 +195,8 @@ public abstract partial class EventBuilder
public void SetAddOnMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
protected abstract void SetAddOnMethodCore(System.Reflection.Emit.MethodBuilder mdBuilder);
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
public void SetRaiseMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
protected abstract void SetRaiseMethodCore(System.Reflection.Emit.MethodBuilder mdBuilder);
public void SetRemoveOnMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
......@@ -224,9 +220,8 @@ public abstract partial class FieldBuilder : System.Reflection.FieldInfo
public void SetConstant(object? defaultValue) { }
protected abstract void SetConstantCore(object? defaultValue);
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
public void SetOffset(int iOffset) { }
protected abstract void SetOffsetCore(int iOffset);
public override void SetValue(object? obj, object? val, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder? binder, System.Globalization.CultureInfo? culture) { }
......@@ -327,9 +322,8 @@ public abstract partial class GenericTypeParameterBuilder : System.Reflection.Ty
public void SetBaseTypeConstraint([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type? baseTypeConstraint) { }
protected abstract void SetBaseTypeConstraintCore([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] Type? baseTypeConstraint);
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
public void SetGenericParameterAttributes(System.Reflection.GenericParameterAttributes genericParameterAttributes) { }
protected abstract void SetGenericParameterAttributesCore(System.Reflection.GenericParameterAttributes genericParameterAttributes);
public void SetInterfaceConstraints(params System.Type[]? interfaceConstraints) { }
......@@ -380,9 +374,8 @@ public abstract partial class MethodBuilder : System.Reflection.MethodInfo
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")]
public override System.Reflection.MethodInfo MakeGenericMethod(params System.Type[] typeArguments) { throw null; }
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
public void SetImplementationFlags(System.Reflection.MethodImplAttributes attributes) { }
protected abstract void SetImplementationFlagsCore(System.Reflection.MethodImplAttributes attributes);
public void SetParameters(params System.Type[] parameterTypes) { }
......@@ -474,9 +467,8 @@ public abstract partial class ModuleBuilder : System.Reflection.Module
[System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("Trimming changes metadata tokens")]
public override System.Type ResolveType(int metadataToken, System.Type[]? genericTypeArguments, System.Type[]? genericMethodArguments) { throw null; }
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
}
public abstract partial class PropertyBuilder : System.Reflection.PropertyInfo
{
......@@ -503,9 +495,8 @@ public abstract partial class PropertyBuilder : System.Reflection.PropertyInfo
public void SetConstant(object? defaultValue) { }
protected abstract void SetConstantCore(object? defaultValue);
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
public void SetGetMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
protected abstract void SetGetMethodCore(System.Reflection.Emit.MethodBuilder mdBuilder);
public void SetSetMethod(System.Reflection.Emit.MethodBuilder mdBuilder) { }
......@@ -671,9 +662,8 @@ public abstract partial class TypeBuilder : System.Reflection.TypeInfo
public override System.Type MakeGenericType(params System.Type[] typeArguments) { throw null; }
public override System.Type MakePointerType() { throw null; }
public void SetCustomAttribute(System.Reflection.ConstructorInfo con, byte[] binaryAttribute) { }
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, byte[] binaryAttribute);
public void SetCustomAttribute(System.Reflection.Emit.CustomAttributeBuilder customBuilder) { }
protected abstract void SetCustomAttributeCore(System.Reflection.Emit.CustomAttributeBuilder customBuilder);
protected abstract void SetCustomAttributeCore(System.Reflection.ConstructorInfo con, System.ReadOnlySpan<byte> binaryAttribute);
public void SetParent([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type? parent) { }
protected abstract void SetParentCore([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.All)] System.Type? parent);
public override string ToString() { throw null; }
......
......@@ -141,7 +141,25 @@
<data name="NotSupported_DynamicModule" xml:space="preserve">
<value>The invoked member is not supported in a dynamic module.</value>
</data>
<data name="Argument_InvalidName" xml:space="preserve">
<value>Invalid name.</value>
<data name="Argument_InvalidTypeArgument" xml:space="preserve">
<value>The type code may not be used as a type argument of a custom attribute .</value>
</data>
<data name="InvalidOperation_EmptyFieldForCustomAttribute" xml:space="preserve">
<value>Custom attribute '{0}' doesn't contain a field named '{1}'.</value>
</data>
<data name="Argument_InvalidCustomAttributeLength" xml:space="preserve">
<value>Custom attribute '{0}' data length is only '{1}'.</value>
</data>
<data name="Argument_InvalidProlog" xml:space="preserve">
<value>Custom attribute '{0}' prolog invalid.</value>
</data>
<data name="Argument_UnknownNamedType" xml:space="preserve">
<value>Custom attribute '{0}' has unknown named type '{1}'.</value>
</data>
<data name="NotImplemented_TypeForValue" xml:space="preserve">
<value>Type '{0}' not handled in the custom attribute value decoder.</value>
</data>
<data name="Argument_DllNameCannotBeEmpty" xml:space="preserve">
<value>DllName cannot be empty.</value>
</data>
</root>
\ No newline at end of file
......@@ -5,6 +5,7 @@
<ContractTypesPartiallyMoved>true</ContractTypesPartiallyMoved>
</PropertyGroup>
<ItemGroup>
<Compile Include="System\Reflection\Emit\CustomAttributeWrapper.cs" />
<Compile Include="System\Reflection\Emit\AssemblyBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\FieldBuilderImpl.cs" />
<Compile Include="System\Reflection\Emit\MethodBuilderImpl.cs" />
......
......@@ -17,6 +17,8 @@ internal sealed class AssemblyBuilderImpl : AssemblyBuilder
private ModuleBuilderImpl? _module;
private bool _previouslySaved;
internal List<CustomAttributeWrapper>? _customAttributes;
internal AssemblyBuilderImpl(AssemblyName name, Assembly coreAssembly, IEnumerable<CustomAttributeBuilder>? assemblyAttributes)
{
ArgumentNullException.ThrowIfNull(name);
......@@ -77,7 +79,7 @@ internal void Save(Stream stream)
}
// Add assembly metadata
_metadataBuilder.AddAssembly(
AssemblyDefinitionHandle assemblyHandle = _metadataBuilder.AddAssembly(
_metadataBuilder.GetOrAddString(value: _assemblyName.Name!),
version: _assemblyName.Version ?? new Version(0, 0, 0, 0),
culture: _assemblyName.CultureName == null ? default : _metadataBuilder.GetOrAddString(value: _assemblyName.CultureName),
......@@ -88,6 +90,7 @@ internal void Save(Stream stream)
#pragma warning restore SYSLIB0037
);
_module.WriteCustomAttributes(_customAttributes, assemblyHandle);
// Add module's metadata
_module.AppendMetadata();
......@@ -128,8 +131,10 @@ protected override ModuleBuilder DefineDynamicModuleCore(string name)
return null;
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
_customAttributes ??= new List<CustomAttributeWrapper>();
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Buffers.Binary;
using System.Diagnostics.CodeAnalysis;
using System.Reflection.Metadata;
namespace System.Reflection.Emit
{
internal readonly struct CustomAttributeWrapper
{
private readonly ConstructorInfo _constructorInfo;
private readonly byte[] _binaryAttribute;
public CustomAttributeWrapper(ConstructorInfo constructorInfo, ReadOnlySpan<byte> binaryAttribute)
{
_constructorInfo = constructorInfo;
_binaryAttribute = binaryAttribute.ToArray(); // TODO: Update to BlobHandle when public API public APi for MetadataBuilder.GetOrAddBlob(ReadOnlySpan<byte>) added
}
public ConstructorInfo Ctor => _constructorInfo;
public byte[] Data => _binaryAttribute;
}
internal struct CustomAttributeInfo
{
public ConstructorInfo _ctor;
public object?[] _ctorArgs;
public string[] _namedParamNames;
public object?[] _namedParamValues;
private const int Field = 0x53;
private const int EnumType = 0x55;
private const int NullValue = 0xff;
private const int OneByteMask = 0x7f;
private const int TwoByteMask = 0x3f;
private const int FourByteMask = 0x1f;
internal static CustomAttributeInfo DecodeCustomAttribute(ConstructorInfo ctor, ReadOnlySpan<byte> binaryAttribute)
{
int pos = 2;
CustomAttributeInfo info = default;
if (binaryAttribute.Length < 2)
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidCustomAttributeLength, ctor.DeclaringType, binaryAttribute.Length), nameof(binaryAttribute));
}
if ((binaryAttribute[0] != 0x01) || (binaryAttribute[1] != 0x00))
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidProlog, ctor.DeclaringType), nameof(binaryAttribute));
}
ParameterInfo[] pi = ctor.GetParameters();
info._ctor = ctor;
info._ctorArgs = new object?[pi.Length];
for (int i = 0; i < pi.Length; ++i)
{
info._ctorArgs[i] = DecodeCustomAttributeValue(pi[i].ParameterType, binaryAttribute, pos, out pos);
}
int numNamed = BinaryPrimitives.ReadUInt16LittleEndian(binaryAttribute.Slice(pos));
pos += 2;
info._namedParamNames = new string[numNamed];
info._namedParamValues = new object[numNamed];
for (int i = 0; i < numNamed; ++i)
{
int namedType = binaryAttribute[pos++];
int dataType = binaryAttribute[pos++];
if (dataType == EnumType)
{
// skip bytes for Enum type name;
int len2 = DecodeLen(binaryAttribute, pos, out pos);
pos += len2;
}
int len = DecodeLen(binaryAttribute, pos, out pos);
string name = StringFromBytes(binaryAttribute, pos, len);
info._namedParamNames[i] = name;
pos += len;
if (namedType == Field)
{
// For known pseudo custom attributes underlying Enum type is int
Type fieldType = dataType == EnumType ? typeof(int) : ElementTypeToType((PrimitiveSerializationTypeCode)dataType);
info._namedParamValues[i] = DecodeCustomAttributeValue(fieldType, binaryAttribute, pos, out pos); ;
}
else
{
throw new ArgumentException(SR.Format(SR.Argument_UnknownNamedType, ctor.DeclaringType, namedType), nameof(binaryAttribute));
}
}
return info;
}
private static string StringFromBytes(ReadOnlySpan<byte> data, int pos, int len)
{
return Text.Encoding.UTF8.GetString(data.Slice(pos, len));
}
private static int DecodeLen(ReadOnlySpan<byte> data, int pos, out int rpos)
{
int len;
if ((data[pos] & 0x80) == 0)
{
len = (data[pos++] & OneByteMask);
}
else if ((data[pos] & 0x40) == 0)
{
len = ((data[pos] & TwoByteMask) << 8) + data[pos + 1];
pos += 2;
}
else
{
len = ((data[pos] & FourByteMask) << 24) + (data[pos + 1] << 16) + (data[pos + 2] << 8) + data[pos + 3];
pos += 4;
}
rpos = pos;
return len;
}
private static object? DecodeCustomAttributeValue(Type t, ReadOnlySpan<byte> data, int pos, out int rpos)
{
switch (Type.GetTypeCode(t))
{
case TypeCode.String:
if (data[pos] == NullValue)
{
rpos = pos + 1;
return null;
}
int len = DecodeLen(data, pos, out pos);
rpos = pos + len;
return StringFromBytes(data, pos, len);
case TypeCode.Int32:
rpos = pos + 4;
return BinaryPrimitives.ReadInt32LittleEndian(data.Slice(pos));
case TypeCode.Int16:
rpos = pos + 2;
return BinaryPrimitives.ReadInt16LittleEndian(data.Slice(pos));
case TypeCode.Boolean:
rpos = pos + 1;
return (data[pos] == 0) ? false : true;
case TypeCode.Object:
int subtype = data[pos];
pos += 1;
if (subtype >= 0x02 && subtype <= 0x0e)
{
return DecodeCustomAttributeValue(ElementTypeToType((PrimitiveSerializationTypeCode)subtype), data, pos, out rpos);
}
break;
}
throw new NotImplementedException(SR.Format(SR.NotImplemented_TypeForValue, t));
}
private static Type ElementTypeToType(PrimitiveSerializationTypeCode elementType) =>
elementType switch
{
PrimitiveSerializationTypeCode.Boolean => typeof(bool),
PrimitiveSerializationTypeCode.Char => typeof(char),
PrimitiveSerializationTypeCode.SByte => typeof(sbyte),
PrimitiveSerializationTypeCode.Byte => typeof(byte),
PrimitiveSerializationTypeCode.Int16 => typeof(short),
PrimitiveSerializationTypeCode.UInt16 => typeof(ushort),
PrimitiveSerializationTypeCode.Int32 => typeof(int),
PrimitiveSerializationTypeCode.UInt32 => typeof(uint),
PrimitiveSerializationTypeCode.Int64 => typeof(long),
PrimitiveSerializationTypeCode.UInt64 => typeof(ulong),
PrimitiveSerializationTypeCode.Single => typeof(float),
PrimitiveSerializationTypeCode.Double => typeof(double),
PrimitiveSerializationTypeCode.String => typeof(string),
_ => throw new ArgumentException(SR.Argument_InvalidTypeArgument, "binaryAttribute"),
};
}
}
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
namespace System.Reflection.Emit
{
......@@ -12,10 +15,14 @@ internal sealed class MethodBuilderImpl : MethodBuilder
private readonly Type _returnType;
private readonly Type[]? _parameterTypes;
private readonly ModuleBuilderImpl _module;
private readonly MethodAttributes _attributes;
private readonly string _name;
private readonly CallingConventions _callingConventions;
private readonly TypeBuilderImpl _declaringType;
private MethodAttributes _attributes;
private MethodImplAttributes _methodImplFlags;
internal DllImportData? _dllImportData;
internal List<CustomAttributeWrapper>? _customAttributes;
internal MethodBuilderImpl(string name, MethodAttributes attributes, CallingConventions callingConventions, Type? returnType,
Type[]? parameterTypes, ModuleBuilderImpl module, TypeBuilderImpl declaringType)
......@@ -35,6 +42,8 @@ internal sealed class MethodBuilderImpl : MethodBuilder
ArgumentNullException.ThrowIfNull(_parameterTypes[i] = parameterTypes[i], nameof(parameterTypes));
}
}
_methodImplFlags = MethodImplAttributes.IL;
}
internal BlobBuilder GetMethodSignatureBlob() =>
......@@ -44,9 +53,44 @@ internal sealed class MethodBuilderImpl : MethodBuilder
protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names) => throw new NotImplementedException();
protected override ParameterBuilder DefineParameterCore(int position, ParameterAttributes attributes, string? strParamName) => throw new NotImplementedException();
protected override ILGenerator GetILGeneratorCore(int size) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder) => throw new NotImplementedException();
protected override void SetImplementationFlagsCore(MethodImplAttributes attributes) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
// Handle pseudo custom attributes
switch (con.ReflectedType!.FullName)
{
case "System.Runtime.CompilerServices.MethodImplAttribute":
int implValue = BinaryPrimitives.ReadUInt16LittleEndian(binaryAttribute.Slice(2));
_methodImplFlags |= (MethodImplAttributes)implValue;
return;
case "System.Runtime.InteropServices.DllImportAttribute":
{
_dllImportData = DllImportData.CreateDllImportData(CustomAttributeInfo.DecodeCustomAttribute(con, binaryAttribute), out var preserveSig);
_attributes |= MethodAttributes.PinvokeImpl;
if (preserveSig)
{
_methodImplFlags |= MethodImplAttributes.PreserveSig;
}
}
return;
case "System.Runtime.InteropServices.PreserveSigAttribute":
_methodImplFlags |= MethodImplAttributes.PreserveSig;
return;
case "System.Runtime.CompilerServices.SpecialNameAttribute":
_attributes |= MethodAttributes.SpecialName;
return;
case "System.Security.SuppressUnmanagedCodeSecurityAttribute":
_attributes |= MethodAttributes.HasSecurity;
break;
}
_customAttributes ??= new List<CustomAttributeWrapper>();
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
protected override void SetImplementationFlagsCore(MethodImplAttributes attributes)
{
_methodImplFlags = attributes;
}
protected override void SetSignatureCore(Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes,
Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) => throw new NotImplementedException();
public override string Name => _name;
......@@ -83,7 +127,7 @@ public override int GetHashCode()
=> throw new NotImplementedException();
public override MethodImplAttributes GetMethodImplementationFlags()
=> throw new NotImplementedException();
=> _methodImplFlags;
public override ParameterInfo[] GetParameters()
=> throw new NotImplementedException();
......@@ -98,4 +142,103 @@ public override object Invoke(object? obj, BindingFlags invokeAttr, Binder? bind
public override MethodInfo MakeGenericMethod(params System.Type[] typeArguments)
=> throw new NotImplementedException();
}
internal sealed class DllImportData
{
private readonly string _moduleName;
private readonly string? _entryPoint;
private readonly MethodImportAttributes _flags;
internal DllImportData(string moduleName, string? entryPoint, MethodImportAttributes flags)
{
_moduleName = moduleName;
_entryPoint = entryPoint;
_flags = flags;
}
public string ModuleName => _moduleName;
public string? EntryPoint => _entryPoint;
public MethodImportAttributes Flags => _flags;
internal static DllImportData CreateDllImportData(CustomAttributeInfo attr, out bool preserveSig)
{
string? moduleName = (string?)attr._ctorArgs[0];
if (moduleName == null || moduleName.Length == 0)
{
throw new ArgumentException(SR.Argument_DllNameCannotBeEmpty);
}
MethodImportAttributes importAttributes = MethodImportAttributes.None;
string? entryPoint = null;
preserveSig = true;
for (int i = 0; i < attr._namedParamNames.Length; ++i)
{
string name = attr._namedParamNames[i];
object value = attr._namedParamValues[i]!;
switch (name)
{
case "PreserveSig":
preserveSig = (bool)value;
break;
case "CallingConvention":
importAttributes |= (CallingConvention)value switch
{
CallingConvention.Cdecl => MethodImportAttributes.CallingConventionCDecl,
CallingConvention.FastCall => MethodImportAttributes.CallingConventionFastCall,
CallingConvention.StdCall => MethodImportAttributes.CallingConventionStdCall,
CallingConvention.ThisCall => MethodImportAttributes.CallingConventionThisCall,
_=> MethodImportAttributes.CallingConventionWinApi // Roslyn defaults with this
};
break;
case "CharSet":
importAttributes |= (CharSet)value switch
{
CharSet.Ansi => MethodImportAttributes.CharSetAnsi,
CharSet.Auto => MethodImportAttributes.CharSetAuto,
CharSet.Unicode => MethodImportAttributes.CharSetUnicode,
_ => MethodImportAttributes.CharSetAuto
};
break;
case "EntryPoint":
entryPoint = (string?)value;
break;
case "ExactSpelling":
if ((bool)value)
{
importAttributes |= MethodImportAttributes.ExactSpelling;
}
break;
case "SetLastError":
if ((bool)value)
{
importAttributes |= MethodImportAttributes.SetLastError;
}
break;
case "BestFitMapping":
if ((bool)value)
{
importAttributes |= MethodImportAttributes.BestFitMappingEnable;
}
else
{
importAttributes |= MethodImportAttributes.BestFitMappingDisable;
}
break;
case "ThrowOnUnmappableChar":
if ((bool)value)
{
importAttributes |= MethodImportAttributes.ThrowOnUnmappableCharEnable;
}
else
{
importAttributes |= MethodImportAttributes.ThrowOnUnmappableCharDisable;
}
break;
}
}
return new DllImportData(moduleName, entryPoint, importAttributes);
}
}
}
......@@ -18,6 +18,9 @@ internal sealed class ModuleBuilderImpl : ModuleBuilder
private readonly Dictionary<Assembly, AssemblyReferenceHandle> _assemblyReferences = new();
private readonly Dictionary<Type, TypeReferenceHandle> _typeReferences = new();
private readonly List<TypeBuilderImpl> _typeDefinitions = new();
private readonly Dictionary<ConstructorInfo, MemberReferenceHandle> _ctorReferences = new();
private Dictionary<string, ModuleReferenceHandle>? _moduleReferences;
private List<CustomAttributeWrapper>? _customAttributes;
private int _nextTypeDefRowId = 1;
private int _nextMethodDefRowId = 1;
private int _nextFieldDefRowId = 1;
......@@ -34,7 +37,7 @@ internal ModuleBuilderImpl(string name, Assembly coreAssembly, MetadataBuilder b
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode", Justification = "Types are preserved via s_coreTypes")]
internal Type GetTypeFromCoreAssembly(CoreTypeId typeId)
internal Type GetTypeFromCoreAssembly(CoreTypeId typeId)
{
if (_coreTypes == null)
{
......@@ -97,7 +100,7 @@ internal Type GetTypeFromCoreAssembly(CoreTypeId typeId)
internal void AppendMetadata()
{
// Add module metadata
_metadataBuilder.AddModule(
ModuleDefinitionHandle moduleHandle = _metadataBuilder.AddModule(
generation: 0,
moduleName: _metadataBuilder.GetOrAddString(_name),
mvid: _metadataBuilder.GetOrAddGuid(Guid.NewGuid()),
......@@ -111,7 +114,9 @@ internal void AppendMetadata()
name: _metadataBuilder.GetOrAddString("<Module>"),
baseType: default,
fieldList: MetadataTokens.FieldDefinitionHandle(1),
methodList: MetadataTokens.MethodDefinitionHandle(1)); ;
methodList: MetadataTokens.MethodDefinitionHandle(1));
WriteCustomAttributes(_customAttributes, moduleHandle);
// Add each type definition to metadata table.
foreach (TypeBuilderImpl typeBuilder in _typeDefinitions)
......@@ -124,22 +129,100 @@ internal void AppendMetadata()
TypeDefinitionHandle typeDefinitionHandle = AddTypeDefinition(typeBuilder, parent, _nextMethodDefRowId, _nextFieldDefRowId);
Debug.Assert(typeBuilder._handle.Equals(typeDefinitionHandle));
WriteCustomAttributes(typeBuilder._customAttributes, typeDefinitionHandle);
// Add each method definition to metadata table.
foreach (MethodBuilderImpl method in typeBuilder._methodDefStore)
foreach (MethodBuilderImpl method in typeBuilder._methodDefinitions)
{
AddMethodDefinition(method, method.GetMethodSignatureBlob());
MethodDefinitionHandle methodHandle = AddMethodDefinition(method, method.GetMethodSignatureBlob());
WriteCustomAttributes(method._customAttributes, methodHandle);
_nextMethodDefRowId++;
if (method._dllImportData != null)
{
AddMethodImport(methodHandle, method._dllImportData.EntryPoint ?? method.Name,
method._dllImportData.Flags, GetModuleReference(method._dllImportData.ModuleName));
}
}
foreach (FieldBuilderImpl field in typeBuilder._fieldDefStore)
foreach (FieldBuilderImpl field in typeBuilder._fieldDefinitions)
{
AddFieldDefinition(field, MetadataSignatureHelper.FieldSignatureEncoder(field.FieldType, this));
FieldDefinitionHandle fieldHandle = AddFieldDefinition(field, MetadataSignatureHelper.FieldSignatureEncoder(field.FieldType, this));
WriteCustomAttributes(field._customAttributes, fieldHandle);
_nextFieldDefRowId++;
if (field._offset > 0 && (typeBuilder.Attributes & TypeAttributes.ExplicitLayout) != 0)
{
AddFieldLayout(fieldHandle, field._offset);
}
if (field._marshallingInfo != null)
{
AddFieldMarshalling(fieldHandle, field._marshallingInfo.PopulateMarshallingBlob(_metadataBuilder));
}
}
}
}
private ModuleReferenceHandle GetModuleReference(string moduleName)
{
_moduleReferences ??= new Dictionary<string, ModuleReferenceHandle>();
if (!_moduleReferences.TryGetValue(moduleName, out var handle))
{
handle = AddModuleReference(moduleName);
_moduleReferences.Add(moduleName, handle);
}
return handle;
}
internal void WriteCustomAttributes(List<CustomAttributeWrapper>? customAttributes, EntityHandle parent)
{
if (customAttributes != null)
{
foreach (CustomAttributeWrapper customAttribute in customAttributes)
{
_metadataBuilder.AddCustomAttribute(parent, GetConstructorHandle(customAttribute.Ctor),
_metadataBuilder.GetOrAddBlob(customAttribute.Data));
}
}
}
private MemberReferenceHandle GetConstructorHandle(ConstructorInfo constructorInfo)
{
if (!_ctorReferences.TryGetValue(constructorInfo, out var constructorHandle))
{
TypeReferenceHandle parentHandle = GetTypeReference(constructorInfo.DeclaringType!);
constructorHandle = AddConstructorReference(parentHandle, constructorInfo);
_ctorReferences.Add(constructorInfo, constructorHandle);
}
return constructorHandle;
}
private TypeReferenceHandle GetTypeReference(Type type)
{
if (!_typeReferences.TryGetValue(type, out var typeHandle))
{
typeHandle = AddTypeReference(type, GetAssemblyReference(type.Assembly));
_typeReferences.Add(type, typeHandle);
}
return typeHandle;
}
private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly)
{
if (!_assemblyReferences.TryGetValue(assembly, out var handle))
{
AssemblyName aName = assembly.GetName();
handle = AddAssemblyReference(aName.Name!, aName.Version, aName.CultureName, aName.GetPublicKeyToken(), aName.Flags, aName.ContentType);
_assemblyReferences.Add(assembly, handle);
}
return handle;
}
private FieldDefinitionHandle AddFieldDefinition(FieldBuilderImpl field, BlobBuilder fieldSignature) =>
_metadataBuilder.AddFieldDefinition(
attributes: field.Attributes,
......@@ -158,45 +241,48 @@ internal void AppendMetadata()
private MethodDefinitionHandle AddMethodDefinition(MethodBuilderImpl method, BlobBuilder methodSignature) =>
_metadataBuilder.AddMethodDefinition(
attributes: method.Attributes,
implAttributes: MethodImplAttributes.IL,
implAttributes: method.GetMethodImplementationFlags(),
name: _metadataBuilder.GetOrAddString(method.Name),
signature: _metadataBuilder.GetOrAddBlob(methodSignature),
bodyOffset: -1, // No body supported yet
parameterList: MetadataTokens.ParameterHandle(1)
);
parameterList: MetadataTokens.ParameterHandle(1));
private TypeReferenceHandle AddTypeReference(Type type, AssemblyReferenceHandle parent) =>
_metadataBuilder.AddTypeReference(
resolutionScope: parent,
@namespace: (type.Namespace == null) ? default : _metadataBuilder.GetOrAddString(type.Namespace),
name: _metadataBuilder.GetOrAddString(type.Name)
);
name: _metadataBuilder.GetOrAddString(type.Name));
private TypeReferenceHandle GetTypeReference(Type type)
private MemberReferenceHandle AddConstructorReference(TypeReferenceHandle parent, ConstructorInfo method)
{
if (!_typeReferences.TryGetValue(type, out var parentHandle))
{
parentHandle = AddTypeReference(type, GetAssemblyReference(type.Assembly));
_typeReferences.Add(type, parentHandle);
}
return parentHandle;
var blob = MetadataSignatureHelper.ConstructorSignatureEncoder(method.GetParameters(), this);
return _metadataBuilder.AddMemberReference(
parent: parent,
name: _metadataBuilder.GetOrAddString(method.Name),
signature: _metadataBuilder.GetOrAddBlob(blob));
}
private AssemblyReferenceHandle GetAssemblyReference(Assembly assembly)
{
if (!_assemblyReferences.TryGetValue(assembly, out var handle))
{
AssemblyName aName = assembly.GetName();
handle = AddAssemblyReference(aName.Name!, aName.Version, aName.CultureName, aName.GetPublicKeyToken(), aName.Flags, aName.ContentType);
_assemblyReferences.Add(assembly, handle);
}
private void AddMethodImport(MethodDefinitionHandle methodHandle, string name,
MethodImportAttributes attributes, ModuleReferenceHandle moduleHandle) =>
_metadataBuilder.AddMethodImport(
method: methodHandle,
attributes: attributes,
name: _metadataBuilder.GetOrAddString(name),
module: moduleHandle);
return handle;
private ModuleReferenceHandle AddModuleReference(string moduleName) =>
_metadataBuilder.AddModuleReference(moduleName: _metadataBuilder.GetOrAddString(moduleName));
private void AddFieldLayout(FieldDefinitionHandle fieldHandle, int offset) =>
_metadataBuilder.AddFieldLayout(field: fieldHandle, offset: offset);
private void AddFieldMarshalling(FieldDefinitionHandle fieldHandle, BlobHandle descriptor)
{
_metadataBuilder.AddMarshallingDescriptor(fieldHandle, descriptor);
}
private AssemblyReferenceHandle AddAssemblyReference(string name, Version? version,
string? culture, byte[]? publicKeyToken, AssemblyNameFlags flags, AssemblyContentType contentType) =>
private AssemblyReferenceHandle AddAssemblyReference(string name, Version? version, string? culture,
byte[]? publicKeyToken, AssemblyNameFlags flags, AssemblyContentType contentType) =>
_metadataBuilder.AddAssemblyReference(
name: _metadataBuilder.GetOrAddString(name),
version: version ?? new Version(0, 0, 0, 0),
......@@ -233,14 +319,17 @@ internal EntityHandle GetTypeHandle(Type type)
protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr, [DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize)
{
TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId);
TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle);
TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle, packingSize, 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, byte[] binaryAttribute) => throw new NotSupportedException();
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder) => throw new NotSupportedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
_customAttributes ??= new List<CustomAttributeWrapper>();
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
public override int GetSignatureMetadataToken(SignatureHelper signature) => throw new NotImplementedException();
}
}
// 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;
using System.Reflection.Metadata.Ecma335;
......@@ -19,17 +18,37 @@ internal static BlobBuilder FieldSignatureEncoder(Type fieldType, ModuleBuilderI
return fieldSignature;
}
internal static BlobBuilder ConstructorSignatureEncoder(ParameterInfo[]? parameters, ModuleBuilderImpl module)
{
BlobBuilder constructorSignature = new();
new BlobEncoder(constructorSignature).
MethodSignature(isInstanceMethod: true).
Parameters((parameters == null) ? 0 : parameters.Length, out ReturnTypeEncoder retType, out ParametersEncoder parameterEncoder);
retType.Void();
if (parameters != null)
{
Type[]? typeParameters = Array.ConvertAll(parameters, parameter => parameter.ParameterType);
foreach (Type parameter in typeParameters)
{
WriteSignatureForType(parameterEncoder.AddParameter().Type(), parameter, module);
}
}
return constructorSignature;
}
internal static BlobBuilder MethodSignatureEncoder(ModuleBuilderImpl module, Type[]? parameters, Type? returnType, bool isInstance)
{
// Encoding return type and parameters.
BlobBuilder methodSignature = new();
ParametersEncoder parEncoder;
ReturnTypeEncoder retEncoder;
new BlobEncoder(methodSignature).
MethodSignature(isInstanceMethod: isInstance).
Parameters((parameters == null) ? 0 : parameters.Length, out retEncoder, out parEncoder);
Parameters((parameters == null) ? 0 : parameters.Length, out ReturnTypeEncoder retEncoder, out ParametersEncoder parEncoder);
if (returnType != null && returnType != module.GetTypeFromCoreAssembly(CoreTypeId.Void))
{
......
......@@ -3,8 +3,8 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
......@@ -12,22 +12,29 @@ namespace System.Reflection.Emit
{
internal sealed class TypeBuilderImpl : TypeBuilder
{
internal List<MethodBuilderImpl> _methodDefStore = new();
internal List<FieldBuilderImpl> _fieldDefStore = new();
private readonly ModuleBuilderImpl _module;
private readonly string _name;
private readonly string? _namespace;
internal readonly TypeDefinitionHandle _handle;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
private Type? _typeParent;
private TypeAttributes _attributes;
private PackingSize _packingSize;
private int _typeSize;
internal readonly TypeDefinitionHandle _handle;
internal readonly List<MethodBuilderImpl> _methodDefinitions = new();
internal readonly List<FieldBuilderImpl> _fieldDefinitions = new();
internal List<CustomAttributeWrapper>? _customAttributes;
internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, ModuleBuilderImpl module, TypeDefinitionHandle handle)
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, ModuleBuilderImpl module,
TypeDefinitionHandle handle, PackingSize packingSize, int typeSize)
{
_name = fullName;
_module = module;
_attributes = typeAttributes;
_packingSize = packingSize;
_typeSize = typeSize;
SetParent(parent);
_handle = handle;
......@@ -41,8 +48,8 @@ internal sealed class TypeBuilderImpl : TypeBuilder
}
internal ModuleBuilderImpl GetModuleBuilder() => _module;
protected override PackingSize PackingSizeCore => throw new NotImplementedException();
protected override int SizeCore => throw new NotImplementedException();
protected override PackingSize PackingSizeCore => _packingSize;
protected override int SizeCore => _typeSize;
protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type interfaceType) => throw new NotImplementedException();
[return: DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))]
protected override TypeInfo CreateTypeInfoCore() => throw new NotImplementedException();
......@@ -52,7 +59,7 @@ internal sealed class TypeBuilderImpl : TypeBuilder
protected override FieldBuilder DefineFieldCore(string fieldName, Type type, Type[]? requiredCustomModifiers, Type[]? optionalCustomModifiers, FieldAttributes attributes)
{
var field = new FieldBuilderImpl(this, fieldName, type, attributes);
_fieldDefStore.Add(field);
_fieldDefinitions.Add(field);
return field;
}
protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(params string[] names) => throw new NotImplementedException();
......@@ -60,7 +67,7 @@ protected override FieldBuilder DefineFieldCore(string fieldName, Type type, Typ
protected override MethodBuilder DefineMethodCore(string name, MethodAttributes attributes, CallingConventions callingConvention, Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers)
{
MethodBuilderImpl methodBuilder = new(name, attributes, callingConvention, returnType, parameterTypes, _module, this);
_methodDefStore.Add(methodBuilder);
_methodDefinitions.Add(methodBuilder);
return methodBuilder;
}
......@@ -72,8 +79,85 @@ protected override MethodBuilder DefineMethodCore(string name, MethodAttributes
protected override ConstructorBuilder DefineTypeInitializerCore() => throw new NotImplementedException();
protected override FieldBuilder DefineUninitializedDataCore(string name, int size, FieldAttributes attributes) => throw new NotImplementedException();
protected override bool IsCreatedCore() => throw new NotImplementedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder) => throw new NotImplementedException();
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
// Handle pseudo custom attributes
switch (con.ReflectedType!.FullName)
{
case "System.Runtime.InteropServices.StructLayoutAttribute":
ParseStructLayoutAttribute(con, binaryAttribute);
return;
case "System.Runtime.CompilerServices.SpecialNameAttribute":
_attributes |= TypeAttributes.SpecialName;
return;
case "System.SerializableAttribute":
#pragma warning disable SYSLIB0050 // 'TypeAttributes.Serializable' is obsolete: 'Formatter-based serialization is obsolete and should not be used'.
_attributes |= TypeAttributes.Serializable;
#pragma warning restore SYSLIB0050
return;
case "System.Runtime.InteropServices.ComImportAttribute":
_attributes |= TypeAttributes.Import;
return;
case "System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeImportAttribute":
_attributes |= TypeAttributes.WindowsRuntime;
return;
case "System.Security.SuppressUnmanagedCodeSecurityAttribute": // It says has no effect in .NET Core, maybe remove?
_attributes |= TypeAttributes.HasSecurity;
break;
}
_customAttributes ??= new List<CustomAttributeWrapper>();
_customAttributes.Add(new CustomAttributeWrapper(con, binaryAttribute));
}
private void ParseStructLayoutAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
CustomAttributeInfo attributeInfo = CustomAttributeInfo.DecodeCustomAttribute(con, binaryAttribute);
LayoutKind layoutKind = (LayoutKind)attributeInfo._ctorArgs[0]!;
_attributes &= ~TypeAttributes.LayoutMask;
_attributes |= layoutKind switch
{
LayoutKind.Auto => TypeAttributes.AutoLayout,
LayoutKind.Explicit => TypeAttributes.ExplicitLayout,
LayoutKind.Sequential => TypeAttributes.SequentialLayout,
_ => TypeAttributes.AutoLayout,
};
for (int i = 0; i < attributeInfo._namedParamNames.Length; ++i)
{
string name = attributeInfo._namedParamNames[i];
int value = (int)attributeInfo._namedParamValues[i]!;
switch (name)
{
case "CharSet":
switch ((CharSet)value)
{
case CharSet.None:
case CharSet.Ansi:
_attributes &= ~(TypeAttributes.UnicodeClass | TypeAttributes.AutoClass);
break;
case CharSet.Unicode:
_attributes &= ~TypeAttributes.AutoClass;
_attributes |= TypeAttributes.UnicodeClass;
break;
case CharSet.Auto:
_attributes &= ~TypeAttributes.UnicodeClass;
_attributes |= TypeAttributes.AutoClass;
break;
}
break;
case "Pack":
_packingSize = (PackingSize)value;
break;
case "Size":
_typeSize = value;
break;
default:
throw new ArgumentException(SR.Format(SR.Argument_UnknownNamedType, con.DeclaringType, name), nameof(binaryAttribute));
}
}
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2074:DynamicallyAccessedMembers",
Justification = "TODO: Need to figure out how to preserve System.Object public constructor")]
......
......@@ -29,17 +29,6 @@ public void SetCustomAttribute_ConstructorInfo_ByteArray_NullAttributeConstructo
AssertExtensions.Throws<ArgumentNullException>("con", () => typeParams[0].SetCustomAttribute(null, new byte[128]));
}
[Fact]
public void SetCustomAttribute_ConstructorInfo_ByteArray_NullBinaryAttribute_ThrowsArgumentNullException()
{
TypeBuilder type = Helpers.DynamicType(TypeAttributes.Public);
string[] typeParamNames = new string[] { "TFirst" };
GenericTypeParameterBuilder[] typeParams = type.DefineGenericParameters(typeParamNames);
ConstructorInfo attributeConstructor = typeof(HelperAttribute).GetConstructor(new Type[0]);
AssertExtensions.Throws<ArgumentNullException>("binaryAttribute", () => typeParams[0].SetCustomAttribute(attributeConstructor, null));
}
[Fact]
public void SetCustomAttribute_CustomAttributeBuilder()
{
......
......@@ -9,7 +9,7 @@
namespace System.Reflection.Emit.Tests
{
[ConditionalClass(typeof(PlatformDetection), nameof(PlatformDetection.IsNotBrowser))]
public class AssemblySaveTestsWithVariousTypes
public class AssemblySaveWithVariousMembersTests
{
private static readonly AssemblyName s_assemblyName = new AssemblyName("MyDynamicAssembly")
{
......@@ -25,23 +25,9 @@ public void EmptyAssemblyAndModuleTest()
using (TempFile file = TempFile.Create())
{
Assembly assemblyFromDisk = WriteAndLoadAssembly(Type.EmptyTypes, file.Path);
AssemblyName aNameFromDisk = assemblyFromDisk.GetName();
// Test AssemblyName properties
Assert.Equal(s_assemblyName.Name, aNameFromDisk.Name);
Assert.Equal(s_assemblyName.Version, aNameFromDisk.Version);
Assert.Equal(s_assemblyName.CultureInfo, aNameFromDisk.CultureInfo);
Assert.Equal(s_assemblyName.CultureName, aNameFromDisk.CultureName);
Assert.Equal(s_assemblyName.ContentType, aNameFromDisk.ContentType);
// Runtime assemblies adding AssemblyNameFlags.PublicKey in Assembly.GetName() overloads
Assert.Equal(s_assemblyName.Flags | AssemblyNameFlags.PublicKey, aNameFromDisk.Flags);
Assert.Empty(assemblyFromDisk.GetTypes());
Module moduleFromDisk = assemblyFromDisk.Modules.FirstOrDefault();
Assert.NotNull(moduleFromDisk);
Assert.Equal(s_assemblyName.Name, moduleFromDisk.ScopeName);
Assert.Empty(moduleFromDisk.GetTypes());
Assert.Empty(assemblyFromDisk.GetTypes());
AssemblyTools.AssertAssemblyNameAndModule(s_assemblyName, assemblyFromDisk.GetName(), assemblyFromDisk.Modules.FirstOrDefault());
}
}
......@@ -86,51 +72,12 @@ private static void AssertTypesAndTypeMembers(Type[] types, Type[] typesFromDisk
Type sourceType = types[i];
Type typeFromDisk = typesFromDisk[i];
AssertTypeProperties(sourceType, typeFromDisk);
AssertMethods(sourceType.GetMethods(), typeFromDisk.GetMethods());
AssertFields(sourceType.GetFields(), typeFromDisk.GetFields());
}
}
private static void AssertFields(FieldInfo[] declaredFields, FieldInfo[] fieldsFromDisk)
{
Assert.Equal(declaredFields.Length, fieldsFromDisk.Length);
for (int j = 0; j < declaredFields.Length; j++)
{
FieldInfo sourceField = declaredFields[j];
FieldInfo fieldFromDisk = fieldsFromDisk[j];
Assert.Equal(sourceField.Name, fieldFromDisk.Name);
Assert.Equal(sourceField.Attributes, fieldFromDisk.Attributes);
Assert.Equal(sourceField.FieldType.FullName, fieldFromDisk.FieldType.FullName);
AssemblyTools.AssertTypeProperties(sourceType, typeFromDisk);
AssemblyTools.AssertMethods(sourceType.GetMethods(), typeFromDisk.GetMethods());
AssemblyTools.AssertFields(sourceType.GetFields(), typeFromDisk.GetFields());
}
}
private static void AssertMethods(MethodInfo[] sourceMethods, MethodInfo[] methodsFromDisk)
{
Assert.Equal(sourceMethods.Length, methodsFromDisk.Length);
for (int j = 0; j < sourceMethods.Length; j++)
{
MethodInfo sourceMethod = sourceMethods[j];
MethodInfo methodFromDisk = methodsFromDisk[j];
Assert.Equal(sourceMethod.Name, methodFromDisk.Name);
Assert.Equal(sourceMethod.Attributes, methodFromDisk.Attributes);
Assert.Equal(sourceMethod.ReturnType.FullName, methodFromDisk.ReturnType.FullName);
}
}
private static void AssertTypeProperties(Type sourceType, Type typeFromDisk)
{
Assert.Equal(sourceType.Name, typeFromDisk.Name);
Assert.Equal(sourceType.Namespace, typeFromDisk.Namespace);
Assert.Equal(sourceType.Attributes, typeFromDisk.Attributes);
Assert.Equal(sourceType.IsInterface, typeFromDisk.IsInterface);
Assert.Equal(sourceType.IsValueType, typeFromDisk.IsValueType);
}
[Theory]
[MemberData(nameof(VariousInterfacesStructsTestData))]
public void WriteAssemblyWithVariousTypesToStreamAndReadBackTest(Type[] types)
......@@ -149,9 +96,8 @@ public void CreateMembersThatUsesTypeLoadedFromCoreAssemblyTest()
{
using (TempFile file = TempFile.Create())
{
MethodInfo defineDynamicAssemblyMethod = AssemblyTools.PopulateMethods(typeof(string), out MethodInfo saveMethod);
AssemblyBuilder assemblyBuilder = (AssemblyBuilder)defineDynamicAssemblyMethod.Invoke(null,
new object[] { s_assemblyName, typeof(object).Assembly, null });
AssemblyBuilder assemblyBuilder = AssemblyTools.PopulateAssemblyBuilderAndSaveMethod(
s_assemblyName, null, typeof(string), out MethodInfo saveMethod);
ModuleBuilder mb = assemblyBuilder.DefineDynamicModule("My Module");
TypeBuilder tb = mb.DefineType("TestInterface", TypeAttributes.Interface | TypeAttributes.Abstract);
......
......@@ -3,6 +3,8 @@
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Xunit;
namespace System.Reflection.Emit.Tests
{
......@@ -10,23 +12,16 @@ internal static class AssemblyTools
{
internal static void WriteAssemblyToDisk(AssemblyName assemblyName, Type[] types, string fileLocation)
{
WriteAssemblyToDisk(assemblyName, types, fileLocation, null);
}
internal static void WriteAssemblyToDisk(AssemblyName assemblyName, Type[] types, string fileLocation, List<CustomAttributeBuilder> assemblyAttributes)
{
MethodInfo defineDynamicAssemblyMethod = PopulateMethods(typeof(string), out MethodInfo saveMethod);
AssemblyBuilder assemblyBuilder = PopulateAssemblyBuilderAndSaveMethod(
assemblyName, null, typeof(string), out MethodInfo saveMethod);
AssemblyBuilder assemblyBuilder = (AssemblyBuilder)defineDynamicAssemblyMethod.Invoke(null,
new object[] { assemblyName, CoreMetadataAssemblyResolver.s_coreAssembly, assemblyAttributes });
ModuleBuilder mb = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
PopulateMembersForModule(types, mb);
PopulateMembersForModule(mb, types);
saveMethod.Invoke(assemblyBuilder, new object[] { fileLocation });
}
private static void PopulateMembersForModule(Type[] types, ModuleBuilder mb)
private static void PopulateMembersForModule(ModuleBuilder mb, Type[] types)
{
foreach (Type type in types)
{
......@@ -47,33 +42,27 @@ private static void PopulateMembersForModule(Type[] types, ModuleBuilder mb)
internal static void WriteAssemblyToStream(AssemblyName assemblyName, Type[] types, Stream stream)
{
WriteAssemblyToStream(assemblyName, types, stream, null);
}
internal static void WriteAssemblyToStream(AssemblyName assemblyName, Type[] types, Stream stream, List<CustomAttributeBuilder>? assemblyAttributes)
{
MethodInfo defineDynamicAssemblyMethod = PopulateMethods(typeof(Stream), out MethodInfo saveMethod);
AssemblyBuilder assemblyBuilder = (AssemblyBuilder)defineDynamicAssemblyMethod.Invoke(null,
new object[] { assemblyName, CoreMetadataAssemblyResolver.s_coreAssembly, assemblyAttributes });
AssemblyBuilder assemblyBuilder = PopulateAssemblyBuilderAndSaveMethod(
assemblyName, null, typeof(Stream), out MethodInfo saveMethod);
ModuleBuilder mb = assemblyBuilder.DefineDynamicModule(assemblyName.Name);
PopulateMembersForModule(types, mb);
PopulateMembersForModule(mb, types);
saveMethod.Invoke(assemblyBuilder, new object[] { stream });
}
internal static MethodInfo PopulateMethods(Type parameterType, out MethodInfo saveMethod)
internal static AssemblyBuilder PopulateAssemblyBuilderAndSaveMethod(AssemblyName assemblyName,
List<CustomAttributeBuilder>? assemblyAttributes, Type parameterType, out MethodInfo saveMethod)
{
Type assemblyType = Type.GetType(
"System.Reflection.Emit.AssemblyBuilderImpl, System.Reflection.Emit",
throwOnError: true)!;
Type assemblyType = Type.GetType("System.Reflection.Emit.AssemblyBuilderImpl, System.Reflection.Emit", throwOnError: true)!;
saveMethod = assemblyType.GetMethod("Save", BindingFlags.NonPublic | BindingFlags.Instance, new Type[] { parameterType });
return assemblyType.GetMethod("DefinePersistedAssembly", BindingFlags.NonPublic | BindingFlags.Static,
MethodInfo defineDynamicAssemblyMethod = assemblyType.GetMethod("DefinePersistedAssembly", BindingFlags.NonPublic | BindingFlags.Static,
new Type[] { typeof(AssemblyName), typeof(Assembly), typeof(List<CustomAttributeBuilder>) });
return (AssemblyBuilder)defineDynamicAssemblyMethod.Invoke(null,
new object[] { assemblyName, CoreMetadataAssemblyResolver.s_coreAssembly, assemblyAttributes });
}
internal static Assembly LoadAssemblyFromPath(string filePath) =>
......@@ -81,6 +70,60 @@ internal static MethodInfo PopulateMethods(Type parameterType, out MethodInfo sa
internal static Assembly LoadAssemblyFromStream(Stream stream) =>
new MetadataLoadContext(new CoreMetadataAssemblyResolver()).LoadFromStream(stream);
internal static void AssertAssemblyNameAndModule(AssemblyName sourceAName, AssemblyName aNameFromDisk, Module moduleFromDisk)
{
// Runtime assemblies adding AssemblyNameFlags.PublicKey in Assembly.GetName() overloads
Assert.Equal(sourceAName.Flags | AssemblyNameFlags.PublicKey, aNameFromDisk.Flags);
Assert.Equal(sourceAName.Name, aNameFromDisk.Name);
Assert.Equal(sourceAName.Version, aNameFromDisk.Version);
Assert.Equal(sourceAName.CultureInfo, aNameFromDisk.CultureInfo);
Assert.Equal(sourceAName.CultureName, aNameFromDisk.CultureName);
Assert.Equal(sourceAName.ContentType, aNameFromDisk.ContentType);
Assert.NotNull(moduleFromDisk);
Assert.Equal(sourceAName.Name, moduleFromDisk.ScopeName);
Assert.Empty(moduleFromDisk.GetTypes());
}
internal static void AssertTypeProperties(Type sourceType, Type typeFromDisk)
{
Assert.Equal(sourceType.Name, typeFromDisk.Name);
Assert.Equal(sourceType.Namespace, typeFromDisk.Namespace);
Assert.Equal(sourceType.Attributes, typeFromDisk.Attributes);
Assert.Equal(sourceType.IsInterface, typeFromDisk.IsInterface);
Assert.Equal(sourceType.IsValueType, typeFromDisk.IsValueType);
}
internal static void AssertFields(FieldInfo[] declaredFields, FieldInfo[] fieldsFromDisk)
{
Assert.Equal(declaredFields.Length, fieldsFromDisk.Length);
for (int j = 0; j < declaredFields.Length; j++)
{
FieldInfo sourceField = declaredFields[j];
FieldInfo fieldFromDisk = fieldsFromDisk[j];
Assert.Equal(sourceField.Name, fieldFromDisk.Name);
Assert.Equal(sourceField.Attributes, fieldFromDisk.Attributes);
Assert.Equal(sourceField.FieldType.FullName, fieldFromDisk.FieldType.FullName);
}
}
internal static void AssertMethods(MethodInfo[] sourceMethods, MethodInfo[] methodsFromDisk)
{
Assert.Equal(sourceMethods.Length, methodsFromDisk.Length);
for (int j = 0; j < sourceMethods.Length; j++)
{
MethodInfo sourceMethod = sourceMethods[j];
MethodInfo methodFromDisk = methodsFromDisk[j];
Assert.Equal(sourceMethod.Name, methodFromDisk.Name);
Assert.Equal(sourceMethod.Attributes, methodFromDisk.Attributes);
Assert.Equal(sourceMethod.ReturnType.FullName, methodFromDisk.ReturnType.FullName);
}
}
}
// The resolver copied from MLC tests
......
......@@ -62,7 +62,8 @@
<Compile Include="ModuleBuilder\ModuleBuilderGetArrayMethod.cs" />
<Compile Include="ModuleBuilder\ModuleBuilderSetCustomAttribute.cs" />
<Compile Include="ParameterBuilder\ParameterBuilderSetConstant.cs" />
<Compile Include="PersistableAssemblyBuilder\AssemblySaveTestsWithVariousTypes.cs" />
<Compile Include="PersistableAssemblyBuilder\AssemblySaveCustomAttributeTests.cs" />
<Compile Include="PersistableAssemblyBuilder\AssemblySaveWithVariousMembersTests.cs" />
<Compile Include="PersistableAssemblyBuilder\AssemblyTools.cs" />
<Compile Include="PropertyBuilder\PropertyBuilderAddOtherMethod.cs" />
<Compile Include="PropertyBuilder\PropertyBuilderAttributes.cs" />
......
......@@ -77,13 +77,12 @@ internal object Invoke()
return result;
}
internal CustomAttributeBuilder(ConstructorInfo con, byte[] binaryAttribute)
internal CustomAttributeBuilder(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
ArgumentNullException.ThrowIfNull(con);
ArgumentNullException.ThrowIfNull(binaryAttribute);
ctor = con;
data = (byte[])binaryAttribute.Clone();
data = binaryAttribute.ToArray();
/* should we check that the user supplied data is correct? */
}
......@@ -268,7 +267,7 @@ private static bool IsValidValue(Type type, object? value)
}
/* helper methods */
internal static int decode_len(byte[] data, int pos, out int rpos)
internal static int decode_len(ReadOnlySpan<byte> data, int pos, out int rpos)
{
int len;
if ((data[pos] & 0x80) == 0)
......@@ -289,9 +288,9 @@ internal static int decode_len(byte[] data, int pos, out int rpos)
return len;
}
internal static string string_from_bytes(byte[] data, int pos, int len)
internal static string string_from_bytes(ReadOnlySpan<byte> data, int pos, int len)
{
return Text.Encoding.UTF8.GetString(data, pos, len);
return Text.Encoding.UTF8.GetString(data.Slice(pos, len));
}
internal static string? decode_string(byte[] data, int pos, out int rpos)
......@@ -454,7 +453,7 @@ elementType switch
_ => throw new Exception(SR.Format(SR.ArgumentException_InvalidTypeArgument, elementType)),
};
private static object? decode_cattr_value(Type t, byte[] data, int pos, out int rpos)
private static object? decode_cattr_value(Type t, ReadOnlySpan<byte> data, int pos, out int rpos)
{
switch (Type.GetTypeCode(t))
{
......@@ -494,14 +493,19 @@ internal struct CustomAttributeInfo
public object?[] namedParamValues;
}
internal static CustomAttributeInfo decode_cattr(CustomAttributeBuilder customBuilder)
{
byte[] data = customBuilder.Data;
ConstructorInfo ctor = customBuilder.Ctor;
return decode_cattr(ctor, data);
}
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2057:UnrecognizedReflectionPattern",
Justification = "Types referenced from custom attributes are preserved")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern",
Justification = "Types referenced from custom attributes are preserved")]
internal static CustomAttributeInfo decode_cattr(CustomAttributeBuilder customBuilder)
internal static CustomAttributeInfo decode_cattr(ConstructorInfo ctor, ReadOnlySpan<byte> data)
{
byte[] data = customBuilder.Data;
ConstructorInfo ctor = customBuilder.Ctor;
int pos;
CustomAttributeInfo info = default;
......
......@@ -297,8 +297,9 @@ protected override ModuleBuilder DefineDynamicModuleCore(string name)
public override bool IsCollectible => access == (uint)AssemblyBuilderAccess.RunAndCollect;
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -315,11 +316,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
UpdateNativeCustomAttributes(this);
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
/*Warning, @typeArguments must be a mscorlib internal array. So make a copy before passing it in*/
internal static Type MakeGenericType(Type gtd, Type[] typeArguments) =>
new TypeBuilderInstantiation(gtd, typeArguments);
......
......@@ -37,6 +37,7 @@
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Buffers.Binary;
namespace System.Reflection.Emit
{
......@@ -254,20 +255,16 @@ protected override ILGenerator GetILGeneratorCore(int streamSize)
return ilgen;
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
ArgumentNullException.ThrowIfNull(customBuilder);
string? attrname = customBuilder.Ctor.ReflectedType!.FullName;
string? attrname = con.ReflectedType!.FullName;
if (attrname == "System.Runtime.CompilerServices.MethodImplAttribute")
{
byte[] data = customBuilder.Data;
int impla; // the (stupid) ctor takes a short or an int ...
impla = (int)data[2];
impla |= ((int)data[3]) << 8;
int impla = BinaryPrimitives.ReadUInt16LittleEndian(binaryAttribute.Slice(2));
SetImplementationFlags((MethodImplAttributes)impla);
return;
}
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -282,14 +279,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
ArgumentNullException.ThrowIfNull(con);
ArgumentNullException.ThrowIfNull(binaryAttribute);
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
protected override void SetImplementationFlagsCore(MethodImplAttributes attributes)
{
if (type.is_created)
......
......@@ -447,14 +447,9 @@ public override Type MakePointerType()
return SymbolType.FormCompoundType("*", this, 0)!;
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
_tb.SetCustomAttribute(customBuilder);
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
_tb.SetCustomAttribute(con, binaryAttribute);
}
internal override bool IsUserType
......
......@@ -106,15 +106,16 @@ protected override void SetRemoveOnMethodCore(MethodBuilder mdBuilder)
remove_method = mdBuilder;
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
RejectIfCreated();
string? attrname = customBuilder.Ctor.ReflectedType!.FullName;
string? attrname = con.ReflectedType!.FullName;
if (attrname == "System.Runtime.CompilerServices.SpecialNameAttribute")
{
attrs |= EventAttributes.SpecialName;
return;
}
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -129,11 +130,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
private void RejectIfCreated()
{
if (typeb.is_created)
......
......@@ -37,6 +37,7 @@
using System.Globalization;
using System.Runtime.InteropServices;
using System.Diagnostics.CodeAnalysis;
using System.Buffers.Binary;
namespace System.Reflection.Emit
{
......@@ -174,18 +175,14 @@ protected override void SetConstantCore(object? defaultValue)
def_value = defaultValue;
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
RejectIfCreated();
string? attrname = customBuilder.Ctor.ReflectedType!.FullName;
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
string? attrname = con.ReflectedType!.FullName;
if (attrname == "System.Runtime.InteropServices.FieldOffsetAttribute")
{
byte[] data = customBuilder.Data;
offset = (int)data[2];
offset |= ((int)data[3]) << 8;
offset |= ((int)data[4]) << 16;
offset |= ((int)data[5]) << 24;
offset = BinaryPrimitives.ReadInt32LittleEndian(binaryAttribute.Slice(2));
return;
}
#pragma warning disable SYSLIB0050 // FieldAttributes.NotSerialized is obsolete
......@@ -221,12 +218,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
RejectIfCreated();
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
protected override void SetOffsetCore(int iOffset)
{
RejectIfCreated();
......
......@@ -424,8 +424,9 @@ public override Type[] GetGenericParameterConstraints()
get { return mbuilder; }
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -440,12 +441,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
}
}
// FIXME: "unverified implementation"
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
private static NotSupportedException not_supported()
{
return new NotSupportedException();
......
......@@ -34,6 +34,7 @@
//
#if MONO_FEATURE_SRE
using System.Buffers.Binary;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Runtime.InteropServices;
......@@ -381,20 +382,17 @@ internal void ResolveUserTypes()
}
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
switch (customBuilder.Ctor.ReflectedType!.FullName)
switch (con.ReflectedType!.FullName)
{
case "System.Runtime.CompilerServices.MethodImplAttribute":
byte[] data = customBuilder.Data;
int impla; // the (stupid) ctor takes a short or an int ...
impla = (int)data[2];
impla |= ((int)data[3]) << 8;
int impla = BinaryPrimitives.ReadUInt16LittleEndian(binaryAttribute.Slice(2));
iattrs |= (MethodImplAttributes)impla;
return;
case "System.Runtime.InteropServices.DllImportAttribute":
CustomAttributeBuilder.CustomAttributeInfo attr = CustomAttributeBuilder.decode_cattr(customBuilder);
CustomAttributeBuilder.CustomAttributeInfo attr = CustomAttributeBuilder.decode_cattr(con, binaryAttribute);
bool preserveSig = true;
/*
......@@ -453,6 +451,7 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
break;
}
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -467,11 +466,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
protected override void SetImplementationFlagsCore(MethodImplAttributes attributes)
{
RejectIfCreated();
......
......@@ -426,8 +426,9 @@ internal int get_next_table_index(int table, int count)
return index;
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -441,11 +442,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
cattrs[0] = customBuilder;
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
/*
internal ISymbolDocumentWriter? DefineDocument (string url, Guid language, Guid languageVendor, Guid documentType)
{
......
......@@ -159,16 +159,18 @@ protected override void SetConstantCore(object? defaultValue)
def_value = defaultValue;
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
typeb.check_not_created();
string? attrname = customBuilder.Ctor.ReflectedType!.FullName;
string? attrname = con.ReflectedType!.FullName;
if (attrname == "System.Runtime.CompilerServices.SpecialNameAttribute")
{
attrs |= PropertyAttributes.SpecialName;
return;
}
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -183,11 +185,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
protected override void SetGetMethodCore(MethodBuilder mdBuilder)
{
typeb.check_not_created();
......
......@@ -34,6 +34,7 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
using System.Buffers.Binary;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
......@@ -1411,15 +1412,19 @@ public override RuntimeTypeHandle TypeHandle
}
}
protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuilder)
internal void SetCustomAttribute(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
string? attrname = customBuilder.Ctor.ReflectedType!.FullName;
SetCustomAttributeCore(con, binaryAttribute);
}
protected override void SetCustomAttributeCore(ConstructorInfo con, ReadOnlySpan<byte> binaryAttribute)
{
string? attrname = con.ReflectedType!.FullName;
if (attrname == "System.Runtime.InteropServices.StructLayoutAttribute")
{
byte[] data = customBuilder.Data;
int layout_kind; /* the (stupid) ctor takes a short or an int ... */
layout_kind = (int)data[2];
layout_kind |= ((int)data[3]) << 8;
layout_kind = (int)binaryAttribute[2];
layout_kind |= ((int)binaryAttribute[3]) << 8;
attrs &= ~TypeAttributes.LayoutMask;
attrs |= ((LayoutKind)layout_kind) switch
{
......@@ -1429,38 +1434,36 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
_ => throw new Exception(SR.Argument_InvalidKindOfTypeForCA), // we should ignore it since it can be any value anyway...
};
Type ctor_type = customBuilder.Ctor is RuntimeConstructorBuilder builder ? builder.parameters![0] : customBuilder.Ctor.GetParametersInternal()[0].ParameterType;
Type ctor_type = con is RuntimeConstructorBuilder builder ? builder.parameters![0] : con.GetParametersInternal()[0].ParameterType;
int pos = 6;
if (ctor_type.FullName == "System.Int16")
pos = 4;
int nnamed = (int)data[pos++];
nnamed |= ((int)data[pos++]) << 8;
int nnamed = BinaryPrimitives.ReadUInt16LittleEndian(binaryAttribute.Slice(pos++));
pos++;
for (int i = 0; i < nnamed; ++i)
{
//byte named_type = data [pos++];
pos++;
byte type = data[pos++];
byte type = binaryAttribute[pos++];
int len;
string named_name;
if (type == 0x55)
{
len = CustomAttributeBuilder.decode_len(data, pos, out pos);
len = CustomAttributeBuilder.decode_len(binaryAttribute, pos, out pos);
//string named_typename =
CustomAttributeBuilder.string_from_bytes(data, pos, len);
CustomAttributeBuilder.string_from_bytes(binaryAttribute, pos, len);
pos += len;
// FIXME: Check that 'named_type' and 'named_typename' match, etc.
// See related code/FIXME in mono/mono/metadata/reflection.c
}
len = CustomAttributeBuilder.decode_len(data, pos, out pos);
named_name = CustomAttributeBuilder.string_from_bytes(data, pos, len);
len = CustomAttributeBuilder.decode_len(binaryAttribute, pos, out pos);
named_name = CustomAttributeBuilder.string_from_bytes(binaryAttribute, pos, len);
pos += len;
/* all the fields are integers in StructLayout */
int value = (int)data[pos++];
value |= ((int)data[pos++]) << 8;
value |= ((int)data[pos++]) << 16;
value |= ((int)data[pos++]) << 24;
int value = BinaryPrimitives.ReadInt32LittleEndian(binaryAttribute.Slice(pos++));
pos += 3;
switch (named_name)
{
case "CharSet":
......@@ -1520,6 +1523,8 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
is_byreflike_set = 1;
}
CustomAttributeBuilder customBuilder = new CustomAttributeBuilder(con, binaryAttribute);
if (cattrs != null)
{
CustomAttributeBuilder[] new_array = new CustomAttributeBuilder[cattrs.Length + 1];
......@@ -1534,11 +1539,6 @@ protected override void SetCustomAttributeCore(CustomAttributeBuilder customBuil
}
}
protected override void SetCustomAttributeCore(ConstructorInfo con, byte[] binaryAttribute)
{
SetCustomAttributeCore(new CustomAttributeBuilder(con, binaryAttribute));
}
protected override EventBuilder DefineEventCore(string name, EventAttributes attributes, Type eventtype)
{
check_name(nameof(name), name);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册