-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CheckInterfaces is too permissive and not permissive enough #96436
Comments
Tagging subscribers to this area: @dotnet/area-system-reflection-emit Issue DetailsRef: #96327 (comment) Cc @buyaa-n Notice that 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 });
}
}
}
|
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).The text was updated successfully, but these errors were encountered: