【问题标题】:Ninject.Web.Mvc knows about dynamically loaded Controller but ASP.Mvc doesnt?Ninject.Web.Mvc 知道动态加载的 Controller 但 ASP.Mvc 不知道吗?
【发布时间】:2011-09-27 11:05:46
【问题描述】:

目前我有一个相当复杂的项目,作为其中的一部分,我有一个 MEF 层,它纯粹处理插件的加载,然后新加载的插件公开它们在 asp.mvc 中注册的路由和它们的控制器被添加到 Ninject 的绑定中。

然而,当动态添加的路由被命中(并且它们被命中,我已经用路由调试器检查过)时,即使为路由中的插件正确添加了命名空间,问题也会出现。当我说我添加了命名空间时,我的意思如下:

var namespaces = new [] { "MyPlugin.Controllers" };
routeCollection.MapRoute(
                    PluginRoute, "plugin/{action}",
                    new { controller = "Plugin", action = "Default" },
                    namespaces);

只是为了给这种情况更多的背景,我从 NinjectHttpApplication 继承而不做任何其他事情,没有自定义控制器工厂,没有自定义依赖解析器,这正是 Ninject 给我的。然后我将当前活动的内核交给插件,它们自己注册。

现在被命中的路由不起作用,我只会为任何外部路由得到 404,即使它们被命中并且控制器(是的三重检查)已向 Ninject 内核注册。所以我在想,虽然 Ninject 已经注册了类型,但是 Mvc 的 DefaultControllerFactory 在调用时找不到类型:

GetControllerTypeWithinNamespaces(string controllerName, HashSet<string> namespaces)

目前让我感到困惑的一件事是,即使使用正确的命名空间也找不到它......但是只是为了证明我的假设,如果我在 asp mvc 项目中添加插件作为引用并运行它(不更改任何代码,只是插件程序集是项目中的引用,因此它将最终在 bin 目录中)它将起作用。击中路线,我得到所需的输出......

所以此时我想知道,虽然 MEF 托管了外部 DLL,但它并没有以某种方式与当前的 AppDomain 或其他东西共享它……这似乎很奇怪……

目前这对我来说是一个障碍,所以任何建议都会很棒!

【问题讨论】:

  • 您可以尝试使用依赖解析器吗?
  • 当这些插件全部崩溃时,它们在哪里?您是否尝试将它们复制到您正在运行的项目的bin 文件夹中?
  • 我不得不硬着头皮写一些代码来观察插件文件夹,每当有变化时将其移动到 bin 目录中。我很想实现另一种解决方案,但我认为不存在,除了获取程序集并将它们手动加载到 AppDomain 中,但是如果不卸载整个 AppDomain 就无法从那里删除它们,并且如果您开始获得多个他们,一切都会变得一团糟……
  • 您能否提供示例应用程序来演示该问题?要么把它上传到某个地方,要么给我发一封邮件,然后我会看看。
  • 抱歉,Remo 回复晚了,我会尝试复制我当前应用程序的核心方面给你看,看看你是否能看到问题出在哪里,虽然我超级好,但可能几天后此刻很忙。感谢您的回复

标签: asp.net-mvc ninject


【解决方案1】:

似乎DefaultControllerFactory 不知道哪个类型负责处理请求。您必须找出 DefaultControllerFactory 不知道这些控制器的原因,或者提供您自己的实现来处理这些情况。这个问题肯定与 MEF 相关,而不是与 Ninject 相关。

public class MyControllerFactory : DefaultControllerFactory
{
    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        Type controllerType = this.GetControllerType(requestContext, controllerName) ?? this.GetPluginControllerType(requestContext, controllerName)

        return this.GetControllerInstance(requestContext, controllerType);
    }

    private Type GetPluginControllerType(RequestContext requestContext, string controllerName)
    {
        // put your own implementation here
    }
}

另一种解决方案是使用 Ninject 的程序集加载机制而不是 MEF。

【讨论】:

  • 我不知道 Ninject 甚至有这样的机制,如果有的话,我宁愿使用它也不愿在堆栈中添加新技术,它是扩展还是只是这样做的模式?您可以提供的有关该功能的任何信息都会很棒!我仍然觉得奇怪的是 DefaultControllerFactory 找不到类型......因为它在同一个 AppDomain 中(据我所知)并且类型已注册......
  • 其中一个 kernel.Load 重载采用路径扫描包含 NinjectModule 定义的程序集。
  • 嗯,我支持你,不幸的是,我认为这不能解决我的真正问题。理想情况下,我需要能够将接口的一些实例动态加载到列表中。即 IList 插件 {get;set;}。目前这就是我使用 MEF 的全部内容,因此每个插件在运行时都加载到此列表中,也可以添加其他插件。但是,根据您的建议,我认为这只是一种动态获取绑定的方法,我认为这不会满足这一点,因为它只会将列表绑定到一个实例,而不是像 MEF 那样用多个实例填充它。
  • @Grofit 不确定我完全理解你在说什么,但如果你只是在寻找multi-injection, Ninject supports that
  • @RubenBartelink 哇……它什么都做……这几乎是我需要的,我认为这给了我一个新问题要问!
【解决方案2】:

听起来与我有关,当您尝试自己直接从内核实例化类时会发生什么?如果可行,您可以创建自己的控制器工厂:

public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel _kernel;

    public NinjectControllerFactory(IKernel kernel)
    {
        _kernel = kernel;
    }

    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        if (controllerType == null)
            return null;

        return (IController)_kernel.Get(controllerType);
    }
}

虽然这些天使用 mvc 3,但我不关心控制器工厂并进入依赖解析器级别。

public class NinjectDependencyResolver : IDependencyResolver
{
    private IKernel _kernel;

    public NinjectDependencyResolver(IKernel kernel)
    {
        _kernel = kernel;
    }

    public object GetService(Type serviceType)
    {
        return _kernel.TryGet(serviceType);
    }

    public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
    {
        return _kernel.GetAll(serviceType);
    }
}

n.b.两者都需要分别在 application_start 中注册(尽管你只会使用一个)

ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(_kernel));

DependencyResolver.SetResolver(new NinjectDependencyResolver(_kernel));

【讨论】:

    猜你喜欢
    • 2012-12-17
    • 2021-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-31
    相关资源
    最近更新 更多