Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,25 @@ internal void AppendMetadata()
Debug.Assert(typeBuilder._handle.Equals(typeDefinitionHandle));
WriteCustomAttributes(typeBuilder._customAttributes, typeDefinitionHandle);

if ((typeBuilder.Attributes & TypeAttributes.ExplicitLayout) != 0)
{
_metadataBuilder.AddTypeLayout(typeDefinitionHandle, (ushort)typeBuilder.PackingSize, (uint)typeBuilder.Size);
}

if (typeBuilder._interfaces != null)
{
foreach(Type iface in typeBuilder._interfaces)
{
_metadataBuilder.AddInterfaceImplementation(typeDefinitionHandle, GetTypeHandle(iface));
// TODO: need to add interface mapping between interface method and implemented method
}
}

if (typeBuilder.DeclaringType != null)
{
_metadataBuilder.AddNestedType(typeDefinitionHandle, (TypeDefinitionHandle)GetTypeHandle(typeBuilder.DeclaringType));
}

foreach (MethodBuilderImpl method in typeBuilder._methodDefinitions)
{
MethodDefinitionHandle methodHandle = AddMethodDefinition(method, method.GetMethodSignatureBlob(), _nextParameterRowId);
Expand Down Expand Up @@ -331,6 +350,14 @@ internal EntityHandle GetTypeHandle(Type type)

return GetTypeReference(type);
}
internal TypeBuilder DefineNestedType(string name, TypeAttributes attr, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent,
Type[]? interfaces, PackingSize packingSize, int typesize, TypeBuilderImpl? enclosingType)
{
TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId);
TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle, interfaces, packingSize, typesize, enclosingType);
_typeDefinitions.Add(_type);
return _type;
}

[RequiresAssemblyFiles("Returns <Unknown> for modules with no file path")]
public override string Name => "<In Memory Module>";
Expand All @@ -347,10 +374,11 @@ internal EntityHandle GetTypeHandle(Type type)
protected override FieldBuilder DefineInitializedDataCore(string name, byte[] data, FieldAttributes attributes) => throw new NotImplementedException();
[RequiresUnreferencedCode("P/Invoke marshalling may dynamically access members that could be trimmed.")]
protected override MethodBuilder DefinePInvokeMethodCore(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type? returnType, Type[]? parameterTypes, CallingConvention nativeCallConv, CharSet nativeCharSet) => throw new NotImplementedException();
protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr, [DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize)
protected override TypeBuilder DefineTypeCore(string name, TypeAttributes attr,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packingSize, int typesize)
{
TypeDefinitionHandle typeHandle = MetadataTokens.TypeDefinitionHandle(++_nextTypeDefRowId);
TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle, packingSize, typesize);
TypeBuilderImpl _type = new TypeBuilderImpl(name, attr, parent, this, typeHandle, interfaces, packingSize, typesize, null);
_typeDefinitions.Add(_type);
return _type;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,20 @@ internal sealed class TypeBuilderImpl : TypeBuilder
private readonly string? _namespace;
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
private Type? _typeParent;
private readonly TypeBuilderImpl? _declaringType;
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<Type>? _interfaces;
internal List<CustomAttributeWrapper>? _customAttributes;

internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, ModuleBuilderImpl module,
TypeDefinitionHandle handle, PackingSize packingSize, int typeSize)
TypeDefinitionHandle handle, Type[]? interfaces, PackingSize packingSize, int typeSize, TypeBuilderImpl? enclosingType)
{
_name = fullName;
_module = module;
Expand All @@ -37,6 +39,7 @@ internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes,
_typeSize = typeSize;
SetParent(parent);
_handle = handle;
_declaringType = enclosingType;

// Extract namespace from fullName
int idx = _name.LastIndexOf('.');
Expand All @@ -45,12 +48,28 @@ internal TypeBuilderImpl(string fullName, TypeAttributes typeAttributes,
_namespace = _name[..idx];
_name = _name[(idx + 1)..];
}

if (interfaces != null)
{
_interfaces = new List<Type>();
for (int i = 0; i < interfaces.Length; i++)
{
Type @interface = interfaces[i];
// cannot contain null in the interface list
ArgumentNullException.ThrowIfNull(@interface, nameof(interfaces));
_interfaces.Add(@interface);
}
}
}

internal ModuleBuilderImpl GetModuleBuilder() => _module;
protected override PackingSize PackingSizeCore => _packingSize;
protected override int SizeCore => _typeSize;
protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type interfaceType) => throw new NotImplementedException();
protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes.All))] Type interfaceType)
{
_interfaces ??= new List<Type>();
_interfaces.Add(interfaceType);
}
[return: DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))]
protected override TypeInfo CreateTypeInfoCore() => throw new NotImplementedException();
protected override ConstructorBuilder DefineConstructorCore(MethodAttributes attributes, CallingConventions callingConvention, Type[]? parameterTypes, Type[][]? requiredCustomModifiers, Type[][]? optionalCustomModifiers) => throw new NotImplementedException();
Expand All @@ -72,7 +91,12 @@ protected override MethodBuilder DefineMethodCore(string name, MethodAttributes
}

protected override void DefineMethodOverrideCore(MethodInfo methodInfoBody, MethodInfo methodInfoDeclaration) => throw new NotImplementedException();
protected override TypeBuilder DefineNestedTypeCore(string name, TypeAttributes attr, [DynamicallyAccessedMembers((DynamicallyAccessedMemberTypes)(-1))] Type? parent, Type[]? interfaces, Emit.PackingSize packSize, int typeSize) => throw new NotImplementedException();
protected override TypeBuilder DefineNestedTypeCore(string name, TypeAttributes attr,
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? parent, Type[]? interfaces, PackingSize packSize, int typeSize)
{
return _module.DefineNestedType(name, attr, parent, interfaces, packSize, typeSize, this);
}

[RequiresUnreferencedCode("P/Invoke marshalling may dynamically access members that could be trimmed.")]
protected override MethodBuilder DefinePInvokeMethodCore(string name, string dllName, string entryName, MethodAttributes attributes, CallingConventions callingConvention, Type? returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers, CallingConvention nativeCallConv, CharSet nativeCharSet) => throw new NotImplementedException();
protected override PropertyBuilder DefinePropertyCore(string name, PropertyAttributes attributes, CallingConventions callingConvention, Type returnType, Type[]? returnTypeRequiredCustomModifiers, Type[]? returnTypeOptionalCustomModifiers, Type[]? parameterTypes, Type[][]? parameterTypeRequiredCustomModifiers, Type[][]? parameterTypeOptionalCustomModifiers) => throw new NotImplementedException();
Expand Down Expand Up @@ -191,6 +215,8 @@ protected override void SetParentCore([DynamicallyAccessedMembers(DynamicallyAcc
}
}
public override string Name => _name;
public override Type? DeclaringType => _declaringType;
public override Type? ReflectedType => _declaringType;
public override bool IsDefined(Type attributeType, bool inherit) => throw new NotImplementedException();
public override object[] GetCustomAttributes(bool inherit) => throw new NotImplementedException();
public override object[] GetCustomAttributes(Type attributeType, bool inherit) => throw new NotImplementedException();
Expand Down Expand Up @@ -245,7 +271,8 @@ protected override bool IsCOMObjectImpl()
public override Type? GetInterface(string name, bool ignoreCase) => throw new NotSupportedException();

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
public override Type[] GetInterfaces() => throw new NotSupportedException();
public override Type[] GetInterfaces() => _interfaces == null ? EmptyTypes : _interfaces.ToArray();

[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
public override PropertyInfo[] GetProperties(BindingFlags bindingAttr) => throw new NotSupportedException();
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
Expand Down Expand Up @@ -122,6 +123,36 @@ public void CreateMembersThatUsesTypeLoadedFromCoreAssemblyTest()
Assert.Equal("System.Void", method.ReturnType.FullName);
}
}

[Fact]
public void AddInterfaceImplementationTest()
{
using (TempFile file = TempFile.Create())
{
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, null, new Type[] { typeof(IOneMethod)});
tb.AddInterfaceImplementation(typeof(INoMethod));
tb.DefineNestedType("NestedType", TypeAttributes.Interface | TypeAttributes.Abstract);
saveMethod.Invoke(assemblyBuilder, new object[] { file.Path });

Assembly assemblyFromDisk = AssemblyTools.LoadAssemblyFromPath(file.Path);
Type testType = assemblyFromDisk.Modules.First().GetTypes()[0];
Type[] interfaces = testType.GetInterfaces();

Assert.Equal("TestInterface", testType.Name);
Assert.Equal(2, interfaces.Length);

Type iOneMethod = testType.GetInterface("IOneMethod");
Type iNoMethod = testType.GetInterface("INoMethod");
Type[] nt = testType.GetNestedTypes();
Assert.Equal(1, iOneMethod.GetMethods().Length);
Assert.Empty(iNoMethod.GetMethods());
Assert.NotNull(testType.GetNestedType("NestedType", BindingFlags.NonPublic));
}
}
}

// Test Types
Expand Down