C# 无法解析从外部dll加载的控制器

C# 无法解析从外部dll加载的控制器,c#,asp.net-web-api,dependency-injection,inversion-of-control,simple-injector,C#,Asp.net Web Api,Dependency Injection,Inversion Of Control,Simple Injector,我正在使用MVC4 Web API和IoC容器(在本例中是简单的注入器,但我认为这个问题与该容器无关)构建一个Web API,它应该公开各种CRUD和查询操作。在我的案例中使用IOC的原因是,我们是一家开发商店,我需要能够让客户构建他们自己的web API控制器,以公开他们需要的数据,从而从我们的系统中公开需要的数据。因此,我希望设计我的解决方案,通过使所有控制器(包括我们的控制器和我们的客户控制器)都是外部的,并且可以通过IOC加载,从而使我能够跟踪自己的产品 网站没有对库的任何引用,但库包含

我正在使用MVC4 Web API和IoC容器(在本例中是简单的注入器,但我认为这个问题与该容器无关)构建一个Web API,它应该公开各种CRUD和查询操作。在我的案例中使用IOC的原因是,我们是一家开发商店,我需要能够让客户构建他们自己的web API控制器,以公开他们需要的数据,从而从我们的系统中公开需要的数据。因此,我希望设计我的解决方案,通过使所有控制器(包括我们的控制器和我们的客户控制器)都是外部的,并且可以通过IOC加载,从而使我能够跟踪自己的产品

网站没有对库的任何引用,但库包含我希望在网站中使用的控制器。这些类型在容器中注册,并且DependencyResolver设置为自定义依赖项解析程序。我有找到dll插件并加载控制器类型的代码,但当我尝试导航到它将表示的路由时,它说找不到它

i、 e.如果我尝试导航到/api/Test1Api,我会看到文本“hello world”

我这里的问题是,虽然我已经加载了控制器类型,但我无法将其转换为网站所说的路由

我得到了错误

未找到与请求URI匹配的HTTP资源

未找到与名为“Test1Api”的控制器匹配的类型

下面是我如何注册容器的

public static class SimpleInjectorInitializer
{
    /// <summary>Initialize the container and register it as MVC3 Dependency Resolver.</summary>
    public static void Initialize()
    {
        //// Did you know the container can diagnose your configuration? Go to: http://bit.ly/YE8OJj.

        // 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)
    {
        var appPath = AppDomain.CurrentDomain.BaseDirectory;

        string[] files = Directory.GetFiles(appPath + "\\bin\\Plugins", "*.dll",
            SearchOption.AllDirectories);
        var assemblies = files.Select(Assembly.LoadFile);

        // register Web API controllers
        var apiControllerTypes =
            from assembly in assemblies
            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 type;

        // register MVC controllers
        var mvcControllerTypes =
            from assembly in assemblies
            where !assembly.IsDynamic
            from type in assembly.GetExportedTypes()
            where typeof(IController).IsAssignableFrom(type)
            where !type.IsAbstract
            where !type.IsGenericTypeDefinition
            where type.Name.EndsWith("Controller", StringComparison.Ordinal)
            select type;

        foreach (var controllerType in apiControllerTypes)
        {
            container.Register(controllerType);
        }

        foreach (var controllerType in mvcControllerTypes)
        {
            container.Register(controllerType);
        }
    }
}
公共静态类SimpleInjector初始值设定项
{
///初始化容器并将其注册为MVC3依赖项解析器。
公共静态void Initialize()
{
////您知道容器可以诊断您的配置吗?转到:http://bit.ly/YE8OJj.
//创建IOC容器。
var container=新容器();
初始化容器(容器);
container.RegisterMvcAttributeFilterProvider();
//验证容器配置
container.Verify();
//注册依赖项解析器。
GlobalConfiguration.Configuration.DependencyResolver=
新的SimpleInjectorWebApidencyResolver(容器);
}
私有静态void InitializeContainer(容器)
{
var appPath=AppDomain.CurrentDomain.BaseDirectory;
string[]files=Directory.GetFiles(appPath+“\\bin\\Plugins”、“*.dll”,
SearchOption.AllDirectories);
var assemblies=files.Select(Assembly.LoadFile);
//注册Web API控制器
var apiControllerTypes=
从程序集中的程序集
哪里!assembly.IsDynamic
来自程序集中的类型。GetExportedTypes()
其中typeof(IHttpController).IsAssignableFrom(类型)
在哪里!输入IsAbstract
其中!type.IsGenericTypeDefinition
其中type.Name.EndsWith(“控制器”,StringComparison.Ordinal)
选择类型;
//注册MVC控制器
var mvcControllerTypes=
从程序集中的程序集
哪里!assembly.IsDynamic
来自程序集中的类型。GetExportedTypes()
其中typeof(IController).IsAssignableFrom(type)
在哪里!输入IsAbstract
其中!type.IsGenericTypeDefinition
其中type.Name.EndsWith(“控制器”,StringComparison.Ordinal)
选择类型;
foreach(apiControllerTypes中的变量控制器类型)
{
容器。寄存器(控制器类型);
}
foreach(mvcControllerTypes中的var controllerType)
{
容器。寄存器(控制器类型);
}
}
}
非常感谢您的帮助。

我想出来了

因此,我在Web Api调用CustomAssembliesResolver中创建了一个新类,该类继承自DefaultAssembliesResolver。实际上,我将我的程序集添加到查找控制器时解析的程序集列表中。我仍然有使用简单注入器的代码用于解决方案的DI部分

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;
    }
}
希望这对别人有帮助


非常非常感谢你对他的帮助和洞察力!我真的很感激

关于您的解决方案的一个重大警告。将控制器注册到容器中也是非常重要的(此建议适用于所有DI框架,尽管某些框架默认情况下也会强制您注册具体类型)。否则你肯定会被同样的问题所困扰

由于
IHttpControllerTypeResolver
使用了
iAssemblisResolver
,因此最简单(也是最安全)的解决方案就是简单地要求
IHttpControllerTypeResolver
注册所有控件。在这种情况下,您的
SimpleInjector初始值设定项将如下所示:

公共静态类SimpleInjector初始值设定项
{
公共静态void Initialize()
{
//创建IOC容器。
var container=新容器();
初始化容器(容器);
container.RegisterMvcAttributeFilterProvider();
//验证容器配置
container.Verify();
//注册依赖项解析器。
GlobalConfiguration.Configuration.DependencyResolver=
新的SimpleInjectorWebApidencyResolver(容器);
}
私有静态void InitializeContainer(容器)
{
GlobalConfiguration.Configuration.Services
.更换(类型为(iAssemblisResolver),
新的CustomAssembliesResolver());
var services=GlobalConfiguration.Configuration.services;
var controllerTypes=services.GetHttpControllerTypeResolver()
.GetControllerTypes(services.GetAssembliesResolver());
//注册Web API控制器(重要!)
foreach(controllerTypes中的var controllerType)
{
容器。寄存器(控制器类型);
}        
}
}
还请注意,您的<
GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());