Mat*_*att 5 c# asp.net-mvc mef autofac
我在使用Autofac构造函数注入时遇到了麻烦.我有点解决了我的问题,但我转向社区寻求完整的解决方案.
这适用于DI
builder.RegisterControllers(typeof(MvcApplication).Assembly)
.InstancePerHttpRequest();
Run Code Online (Sandbox Code Playgroud)
事实并非如此.
builder.RegisterControllers(typeof(MvcApplication).Assembly)
.AsImplementedInterfaces()
.InstancePerHttpRequest();
Run Code Online (Sandbox Code Playgroud)
这是我的控制器.
public class HomeController : BaseController
{
public HomeController(IPlugin plugin)
{
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个模块来解决IPlugin注入问题.我想知道为什么我需要.AsImplementedInterfaces()出去做这项工作.我更喜欢使用接口,因为我在运行时使用MEF从其他程序集导入IControllers.
更新
感谢japonex(见下面的评论)我已经更新了我的解决方案.这就是我为使一切工作所做的一切.
首先,我的项目有自己的控制器,然后我使用MEF从其他程序集导入控制器.
我当前项目的控制器必须在没有.AsImplementedInterfaces()调用的情况下注册,所以就这样
builder.RegisterControllers(typeof(MvcApplication).Assembly).InstancePerRequest();
Run Code Online (Sandbox Code Playgroud)
这将使用类型而不是作为接口(MyProject.Controllers.HomeController而不是System.Web.Mvc.IController)将控制器置于Autofac中.
接下来在我的插件项目中,我只需要导出类型而不是作为接口.所以我用这个
[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : PluginController
Run Code Online (Sandbox Code Playgroud)
而不是这个
[Export(typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : PluginController
Run Code Online (Sandbox Code Playgroud)
注意Export属性的差异.
接下来我将电流DependencyResolver设置为AutofacDependencyResolver.
最后,但并非最不重要的是,我创建了一个自定义ControllerFactory来创建控制器.从技术上讲,这不是必需的,因为我不再使用接口,但我有代码在创建之前检查控制器的状态.这允许我从管理区域轻松启用/禁用插件.
所以问题的根源是Autofac需要类型而不是接口才能正确解析.我确信这可以用接口完成,但这个解决方案对我有用.我想要使用接口的唯一真正原因是因为我可以在不知道其类型的情况下向Autofac请求所有控制器.
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;
}
}
Run Code Online (Sandbox Code Playgroud)
当您使用时,.AsImplementedInterfaces您是说对于每个具体类型,Autofac 都会为每个接口实现注册该类型。
因此,您将程序集中的所有控制器注册到 IController,并且可能是因为您没有任何规则(键控或命名注册)来决定返回哪个具体类型,Autofac 可能会返回 IController 的最后一个注册。
尝试调用container.Resolve并看看你会得到什么。
考虑一下,如果您有:
public class HomeController : BaseController
{
public HomeController(IPlugin plugin)
{
}
}
Run Code Online (Sandbox Code Playgroud)
和
public class Home2Controller : BaseController
{
public Home2Controller(IPlugin plugin)
{
}
}
Run Code Online (Sandbox Code Playgroud)
HomeController 将注册到 IController,Home2Controller 也将注册到 IController。
我认为如果您不使用任何类型的规则(键控或命名注册),Autofac 的默认行为是使用最后一次注册
| 归档时间: |
|
| 查看次数: |
8487 次 |
| 最近记录: |