-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Closed
Closed
Copy link
Milestone
Description
Description
We are loading our plugins and their dependencies in a custom load context, except for the .NET runtime assemblies which are used from the default context.
One of our dependencies is loaded in both Default and plugin context since it is used by both host and plugins.
This dependency is using (Base)DispatchProxy.Create<IProxy, Base> which succeeds in default context but fails in plugin context with InvalidCastException.
Reproduction Steps
public class Program : DispatchProxy
{
static void Main()
{
Console.WriteLine(DispatchProxyCreate(typeof(Program)).GetType().IsAssignableTo(typeof(Program)));
// True
var typeofProgramInCustomContext = new AssemblyLoadContext("custom")
.LoadFromAssemblyPath(typeof(Program).Assembly.Location)
.GetType(typeof(Program).FullName);
Console.WriteLine(DispatchProxyCreate(typeofProgramInCustomContext).GetType().IsAssignableTo(typeofProgramInCustomContext));
// False
}
public static object DispatchProxyCreate(Type parentType) => typeof(Program)
.GetMethod(nameof(DispatchProxyCreateGeneric))
.MakeGenericMethod(parentType)
.Invoke(null, null);
public static object DispatchProxyCreateGeneric<T>() where T : DispatchProxy =>
DispatchProxy.Create<IDisposable, T>();
protected override object Invoke(MethodInfo targetMethod, object[] args) => null;
}
Quick investigation reveals that this is induced by the single static AssemblyBuilder used for all proxies, which binds the parent type to the default context.
var typeId = 0;
var moduleBuilder = AssemblyBuilder
.DefineDynamicAssembly(new AssemblyName("assembly"), AssemblyBuilderAccess.Run)
.DefineDynamicModule("module");
Console.WriteLine(CreateDerivedType(typeof(Program)).IsAssignableTo(typeof(Program)));
// True
var typeofProgramInCustomContext = new AssemblyLoadContext("custom")
.LoadFromAssemblyPath(typeof(Program).Assembly.Location)
.GetType(typeof(Program).FullName);
Console.WriteLine(CreateDerivedType(typeofProgramInCustomContext).IsAssignableTo(typeofProgramInCustomContext));
// False
Type CreateDerivedType(Type parentType) => moduleBuilder
.DefineType($"type{typeId++}", TypeAttributes.Public, parentType)
.CreateType();
Reactions are currently unavailable