Unable to resolve a controller that was loaded from external dll

半城伤御伤魂 提交于 2019-12-03 09:02:23
Steven

One big warning about your solution. It is quite crucial to register your controller into your container as well (this advice holds for all DI frameworks, although some frameworks by default force you to register concrete types as well). Otherwise you will certainly get bitten by the same problem as this developer had.

Since the IHttpControllerTypeResolver makes use of the IAssembliesResolver, the simplest (and safest) solution is to simply ask the IHttpControllerTypeResolver for all controls to register. Your SimpleInjectorInitializer in that case will look like this:

public static class SimpleInjectorInitializer
{
    public static void Initialize()
    {
        // Create the IOC container.
        var container = new Container();

        InitializeContainer(container);

        container.RegisterMvcAttributeFilterProvider();

        // Verify the container configuration
        container.Verify();

        // Register the dependency resolver.
        GlobalConfiguration.Configuration.DependencyResolver =
            new SimpleInjectorWebApiDependencyResolver(container);
    }

    private static void InitializeContainer(Container container)
    {
        GlobalConfiguration.Configuration.Services
            .Replace(typeof(IAssembliesResolver),
                new CustomAssembliesResolver());

        var services = GlobalConfiguration.Configuration.Services;
        var controllerTypes = services.GetHttpControllerTypeResolver()
            .GetControllerTypes(services.GetAssembliesResolver());

        // register Web API controllers (important!)
        foreach (var controllerType in controllerTypes)
        {
            container.Register(controllerType);
        }        
    }
}

Also note that your CustomAssembliesResolver can be made considerably easier:

public class CustomAssembliesResolver
    : DefaultAssembliesResolver
{
    private Assembly[] plugins = (
        from file in Directory.GetFiles(
            appPath + "\\bin\\Plugins", "*.dll",
            SearchOption.AllDirectories)
        let assembly = Assembly.LoadFile(file)
        select assembly)
        .ToArray();

    public override ICollection<Assembly> GetAssemblies()
    {
        var appPath =
            AppDomain.CurrentDomain.BaseDirectory;

        return base.GetAssemblies()
            .Union(this.plugins).ToArray();        
    }
}
abraganza

I figured it out!

So I created a new class in my Web Api call CustomAssembliesResolver that inherits from DefaultAssembliesResolver. Essentially I add my assembly to the list of assemblies that are parsed when looking for controllers. I still have the code that uses Simple Injector for the DI portion of the solution.

public class CustomAssembliesResolver : DefaultAssembliesResolver
{
    public override ICollection<Assembly> GetAssemblies()
    {
        var appPath = AppDomain.CurrentDomain.BaseDirectory;
        var baseAssemblies = base.GetAssemblies();
        var assemblies = new List<Assembly>(baseAssemblies);
        var files = Directory.GetFiles(appPath + "\\bin\\Plugins", "*.dll",
                        SearchOption.AllDirectories);
        var customAssemblies = files.Select(Assembly.LoadFile);

        // register Web API controllers
        var apiControllerAssemblies =
            from assembly in customAssemblies
            where !assembly.IsDynamic
            from type in assembly.GetExportedTypes()
            where typeof(IHttpController).IsAssignableFrom(type)
            where !type.IsAbstract
            where !type.IsGenericTypeDefinition
            where type.Name.EndsWith("Controller", StringComparison.Ordinal)
            select assembly;

        foreach (var assembly in apiControllerAssemblies)
        {
            baseAssemblies.Add(assembly);
        }

        return assemblies;
    }
}

I also added the following line to the beginning of the App_Start in the Global.asax.cs

GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());

Hope this helps someone!

A huge, huge thank you to Steven for his help and insight! I really appreciate it!!

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!