gpt4 book ai didi

c# - 将 Autofac 与 Mvc Controller 构造函数注入(inject)结合使用

转载 作者:太空狗 更新时间:2023-10-29 23:45:33 27 4
gpt4 key购买 nike

我在使用 Autofac 构造函数注入(inject)时遇到问题。我的问题在某种程度上得到了解决,但我正转向社区寻求完整的解决方案。

这适用于 DI

builder.RegisterControllers(typeof(MvcApplication).Assembly)
.InstancePerHttpRequest();

这不是。

builder.RegisterControllers(typeof(MvcApplication).Assembly)
.AsImplementedInterfaces()
.InstancePerHttpRequest();

这是我的 Controller 。

public class HomeController : BaseController
{
public HomeController(IPlugin plugin)
{

}
}

我有一个模块可以解决 IPlugin 注入(inject)问题。我想知道为什么我需要取出 .AsImplementedInterfaces() 来完成这项工作。我更愿意使用接口(interface),因为我在运行时使用 MEF 从其他程序集中导入 IController。

更新

感谢 japonex(请参阅下面的评论),我已经更新了我的解决方案。这是我为使一切正常运行所做的工作。

首先我的项目有自己的 Controller ,然后我使用 MEF 从其他程序集中导入 Controller 。

我当前项目的 Controller 必须在没有 .AsImplementedInterfaces() 调用的情况下注册,所以就像这样

builder.RegisterControllers(typeof(MvcApplication).Assembly).InstancePerRequest();

这将使用类型而不是接口(interface)(MyProject.Controllers.HomeController 而不是 System.Web.Mvc.IController)将 Controller 放入 Autofac。

接下来在我的插件项目中,我只需要导出类型而不是作为接口(interface)。所以我用这个

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : PluginController

代替这个

[Export(typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : PluginController

请注意 Export 属性的区别。

接下来,我将当前的 DependencyResolver 设置为 AutofacDependencyResolver

最后但同样重要的是,我创建了一个自定义 ControllerFactory 来创建 Controller 。从技术上讲,这不是必需的,因为我不再使用接口(interface),但我有代码在创建 Controller 之前检查它的状态。这使我可以轻松地从管理区域启用/禁用插件。

所以问题的根源是 Autofac 需要类型而不是接口(interface)来正确解析。我确信这可以通过接口(interface)来完成,但这个解决方案对我有用。我想要使​​用接口(interface)的唯一真正原因是我可以在不知道它们类型的情况下从 Autofac 请求所有 Controller 。

public class MyControllerFactory : DefaultControllerFactory
{
private readonly IContainer _container;

public PortalControllerFactory(IContainer container)
{
_container = container;
}

public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
Type controllerType = GetControllerType(requestContext, controllerName);

if(controllerType == null)
{
throw new HttpException(404, ErrorMessages.Http404);
}

IPlugin plugin = PluginManager.Current.GetPlugin(controllerType);

if (plugin != null && plugin.Status != Common.Enums.PluginStatus.Enabled)
{
//the controller/plugin is disabled so modify the route data and return the controller
RouteData data = new RouteData();
data.Values.Add("controller", "plugin");
data.Values.Add("action", "disabled");
data.Values.Add("plugin", plugin.Name);

requestContext.RouteData = data;

return ViewRenderer.CreateController<Project.Controllers.PluginController>(data);
}

var controller = ((AutofacDependencyResolver)DependencyResolver.Current).RequestLifetimeScope.Resolve(controllerType);
return controller as IController;
}
}

最佳答案

当您使用 .AsImplementedInterfaces 时,您是说对于每个具体类型,Autofac 都会为每个接口(interface)实现注册此类型。

因此,您正在将程序集中的所有 Controller 注册到 IController,并且可能是因为您没有任何规则(键控或命名注册)来决定返回哪个具体类型,Autofac 可能会返回 IController 的最后注册。

尝试调用 container.Resolve 并查看结果。

考虑一下,如果你有:

 public class HomeController : BaseController
{
public HomeController(IPlugin plugin)
{

}
}

  public class Home2Controller : BaseController
{
public Home2Controller(IPlugin plugin)
{

}
}

HomeController 将被注册到 IController 和Home2Controller 也将注册到 IController。

而且我认为如果您不使用任何类型的规则(键控或命名注册),Autofac 的默认行为是使用最后一次注册

关于c# - 将 Autofac 与 Mvc Controller 构造函数注入(inject)结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24833848/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com