当控制器类在不同的程序集中时,如何将Controller注册到ASP.NET MVC中?

qua*_*els 27 c# asp.net asp.net-mvc plugins inversion-of-control

我的目标是修改asp.net mvc的控制器注册表,以便我可以在单独的(子)程序集中创建控制器和视图,只需将View文件和DLL复制到主机MVC应用程序,新控制器就可以"插入" "到主机应用程序.

显然,我需要某种IoC模式,但我很茫然.

我的想法是引用一个带有system.web.mvc的子程序集,然后开始构建继承自Controller以下内容的控制器类:

单独组装:

using System.Web;
using System.Web.Mvc;

namespace ChildApp
{
    public class ChildController : Controller
    {
        ActionResult Index()
        {
            return View();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

可是一切都很好,花花公子.但后来我考虑修改主机应用程序的Controller注册表以在运行时加载我的新子控制器,我感到困惑.也许是因为我需要更深入地了解C#.

无论如何,我以为我需要创建一个CustomControllerFactory类.所以我开始编写一个覆盖该GetControllerInstance()方法的类.当我打字的时候,intellisence突然出现了:

主机MVC应用程序:

public class CustomControllerFactory : DefaultControllerFactory 
{
    protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
    {
        return base.GetControllerInstance(requestContext, controllerType);
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,在这一点上,我很茫然.我不知道那是做什么的.最初,我打算写一个像这样的服务定位器的"Controller Loader"类:

主机MVC应用程序:

public class ControllerLoader
{
    public static IList<IController> Load(string folder)
    {
        IList<IController> controllers = new List<IController>();

        // Get files in folder
        string[] files = Directory.GetFiles(folder, "*.plug.dll");
        foreach(string file in files)
        {
            Assembly assembly = Assembly.LoadFile(file);
            var types = assembly.GetExportedTypes();
            foreach (Type type in types)
            {
                if (type.GetInterfaces().Contains(typeof(IController)))
                {
                    object instance = Activator.CreateInstance(type);
                    controllers.Add(instance as IController);
                }
            }
        }
        return controllers;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后我计划使用我的控制器列表在控制器工厂中注册它们.但是......怎么样?我觉得我正处于搞清楚的边缘.我想这一切都归结为这个问题:我如何勾选return base.GetControllerInstance(requestContext, controllerType);?或者,我应该完全使用不同的方法吗?

Mar*_*ann 27

从"根"ASP.NET MVC项目引用其他程序集.如果控制器在另一个命名空间中,则需要修改global.asax中的路由,如下所示:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
        namespaces: new[] { typeof(HomeController).Namespace }
    );

}
Run Code Online (Sandbox Code Playgroud)

注意方法的附加namespaces参数MapRoute.

  • 那就是那件事.我试图让这个工作无需重新编译每个新的控制器组件的Root/Host应用程序. (3认同)