Closed
Description
Ref: #96327 (comment)
Cc @buyaa-n
Notice that CreateType1
works with ref.emit, but throws an exception in the persistable implementation (the checks incorrectly demand an interface method with a default implementation to be implemented).
Similarly, CreateType2
throws with ref.emit, but works with the persistable implementation (the check fails to notice a static abstract method wasn't implemented).
using System.Reflection.Emit;
using System.Reflection;
namespace TestApp
{
public interface IFoo
{
void Method() => Console.WriteLine("Hello");
}
public interface IBar
{
static abstract void Method();
}
internal class Program
{
static Type CreateType1(ModuleBuilder moduleBuilder)
{
TypeBuilder t = moduleBuilder.DefineType("TestClass1", TypeAttributes.Class, typeof(object), new Type[] { typeof(IFoo) });
ConstructorBuilder cb = t.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes);
ILGenerator ilgen = cb.GetILGenerator();
ilgen.Emit(OpCodes.Ret);
return t.CreateType();
}
static Type CreateType2(ModuleBuilder moduleBuilder)
{
TypeBuilder t = moduleBuilder.DefineType("TestClass2", TypeAttributes.Class, typeof(object), new Type[] { typeof(IBar) });
ConstructorBuilder cb = t.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, Type.EmptyTypes);
ILGenerator ilgen = cb.GetILGenerator();
ilgen.Emit(OpCodes.Ret);
return t.CreateType();
}
static void Main(string[] args)
{
AssemblyName aName = new AssemblyName("MyAssembly");
AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(aName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder = ab.DefineDynamicModule("ModuleName"); // Only one module supported
{
var t = CreateType1(moduleBuilder);
var o = Activator.CreateInstance(t);
Console.WriteLine($"Created type {o.GetType()}");
}
try
{
var t = CreateType2(moduleBuilder);
var o = Activator.CreateInstance(t);
Console.WriteLine(o.GetType());
}
catch (TypeLoadException e)
{
Console.WriteLine(e.Message);
}
ab = PopulateAssemblyBuilderAndSaveMethod(aName, null, out MethodInfo saveMethod);
moduleBuilder = ab.DefineDynamicModule("ModuleName"); // Only one module supported
try
{
var t = CreateType1(moduleBuilder);
Console.WriteLine($"Created type {t}");
}
catch (TypeLoadException e)
{
Console.WriteLine(e.Message);
}
{
var t = CreateType2(moduleBuilder);
Console.WriteLine(t);
}
// Then save the assembly into a file (or Stream)
saveMethod.Invoke(ab, new object[] { "MyAssembly.dll" });
}
private static AssemblyBuilder PopulateAssemblyBuilderAndSaveMethod(AssemblyName assemblyName,
List<CustomAttributeBuilder> assemblyAttributes, out MethodInfo saveMethod)
{
Type abType= Type.GetType("System.Reflection.Emit.AssemblyBuilderImpl, System.Reflection.Emit", throwOnError: true)!;
saveMethod = abType.GetMethod("Save", BindingFlags.NonPublic | BindingFlags.Instance,
new Type[] { typeof(string) /* or use typeof(Stream) */ });
MethodInfo defineDynamicAssembly = abType.GetMethod("DefinePersistedAssembly", BindingFlags.NonPublic | BindingFlags.Static,
new Type[] { typeof(AssemblyName), typeof(Assembly), typeof(List<CustomAttributeBuilder>) });
return (AssemblyBuilder)defineDynamicAssembly.Invoke(null, new object[] { assemblyName, typeof(object).Assembly, assemblyAttributes });
}
}
}