mercredi 11 octobre 2023

Can i force a Type loaded in the default AssemblyLoadContext to return a type loaded in my plugin AssemblyLoadContext?

I am migrating an testing application from .NET Framework to .NET. The main purpose was to start another application and run tests on that application with nunit. For the sake of running multiple Test classes in succession, the application lived isolated in a dedicated AppDomain. In .NET this approach no longer works as there is only ever one AppDomain.

This approach was mainly used to make sure that everything was cleanly initialized (especially in regards to static members).

I am trying to rebuild this isolation with AssemblyLoadContext, by creating a new AssemblyLoadContext and loading all needed assemblies of the application into it and creating the TestSuite within that AssemblyLoadContext.

        private IEnumerable<TestSuite> BuildFrom(ITypeInfo typeInfo, IPreFilter filter)
        {
            foreach (var suite in m_source.BuildFrom(typeInfo, filter))
            {
                m_context = new AssemblyLoadContext(suite.Name, true);
                var assembly = m_context.LoadFromAssemblyPath(typeof(PlatformTestSuite).Assembly.Location);
                m_context.LoadFromAssemblyPath(typeof(TestPlatform).Assembly.Location);
                m_context.LoadFromAssemblyPath(typeof(ServiceManager).Assembly.Location);
                m_context.LoadFromAssemblyPath(typeof(UserInterface).Assembly.Location);

                yield return (TestSuite)assembly.CreateInstance(typeof(PlatformTestSuite).FullName, false, BindingFlags.Default, null, new object[]{suite, m_context}, CultureInfo.CurrentCulture,  null);
            }
        }

This should ensure that all types used in the constructor are loaded from my newly created context. This works for most types, except the following:

var converter = TypeDescriptor.GetConverter(typeof(InformationViewModel));

Here, TypeDescriptor is loaded from the Default AssemblyLoadContext, as it is intended as a shared dependency. InformationViewModel is loaded from my custom context. The resulting type "InformationViewModelConverter" is also loaded from my custom context. However, the resulting converter is of type "InformationViewModelConverter", which is loaded from the Default AssemblyLoadContext. The converter in turn then uses only types loaded from the Default AssemblyLoadContext and cannot convert my types, as they are loaded from a different context.

My question

Is there a way to keep TypeDescriptor in the Default Context as a shared dependency and still make sure that created converter are of the type loaded from my custom context? If possible, this should happen without the programmer needing to think about it when using TypeDescriptor.GetConverter().





Aucun commentaire:

Enregistrer un commentaire