Skip to content

[Question] How to register types from plugins with Microsoft Dependency Injection container #303

@swidz

Description

@swidz

Please find the following example. I was struggling with type registration in DI container and then using service provider to create these types. The error I was getting was that certain type was not registered. I figured out that types should be registered and retrieved using in the same AssemblyLoadContext.

My question is how assembly load contexts are identified and what is the correct way of DI type registration.
In the following example a plugin is loaded using loader created by PluginLoader.CreateFromAssemblyFile(pluginPath).

After building the provider and constructing the scope, if i use the same loader the type is retrieved correctly but if I create another loader from the same assembly path and enter its context then the type is not found in the container.

[TestMethod]
    public void TestServiceProvider()
    {        
        string assemblyName = "MyPluginAssembly";
        string className = "MyPluginAssembly.MyClass";
        string typeName = $"{className}, {assemblyName}";
        string pluginPath = "c:\\plugins\\MyPluginAssembly.dll";

        var services = new ServiceCollection();

        var loader1 = PluginLoader.CreateFromAssemblyFile(pluginPath);        
        using (loader1.EnterContextualReflection())
        {
            Type t1 = Type.GetType(typeName);            
            Assert.IsNotNull(t1);

            var alc1 = AssemblyLoadContext.GetLoadContext(t1.Assembly);

            services.TryAddTransient(t1);            
        }

        var serviceProvider = services.BuildServiceProvider();
        var scope = serviceProvider.CreateScope();

        
        using (loader1.EnterContextualReflection())
        {
            Type t2 = Type.GetType(typeName);
            Assert.IsNotNull(t2);

            var alc2 = AssemblyLoadContext.GetLoadContext(t2.Assembly);
                       
            var i2 = scope.ServiceProvider.GetService(t2);   //i2 is OK

            Assert.IsNotNull(i2);
        }


        var loader2 = PluginLoader.CreateFromAssemblyFile(pluginPath);
        using (loader2.EnterContextualReflection())
        {
            Type t3 = Type.GetType(typeName);
            Assert.IsNotNull(t3);

            var alc2 = AssemblyLoadContext.GetLoadContext(t3.Assembly);

            var i3 = scope.ServiceProvider.GetService(t3);   //i3 is null

            Assert.IsNotNull(i3);
        }

    }

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions