Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用Autofac和Mvc控制器构造函数注入_C#_Asp.net Mvc_Mef_Autofac - Fatal编程技术网

C# 使用Autofac和Mvc控制器构造函数注入

C# 使用Autofac和Mvc控制器构造函数注入,c#,asp.net-mvc,mef,autofac,C#,Asp.net Mvc,Mef,Autofac,我在Autofac构造函数注入方面遇到问题。我的问题在某种程度上解决了,但我正在向社区寻求一个完整的解决方案 这适用于DI builder.RegisterControllers(typeof(MvcApplication).Assembly) .InstancePerHttpRequest(); 但事实并非如此 builder.RegisterControllers(typeof(MvcApplication).Assembly) .AsImplementedIn

我在Autofac构造函数注入方面遇到问题。我的问题在某种程度上解决了,但我正在向社区寻求一个完整的解决方案

这适用于DI

builder.RegisterControllers(typeof(MvcApplication).Assembly)
       .InstancePerHttpRequest();
但事实并非如此

builder.RegisterControllers(typeof(MvcApplication).Assembly)
       .AsImplementedInterfaces()
       .InstancePerHttpRequest();
这是我的控制器

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

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

更新

感谢japonex(见下面的评论),我已经更新了我的解决方案。这是我为让一切正常运转所做的

首先,我的项目有自己的控制器,然后我使用MEF从其他程序集导入控制器

当前项目的控制器必须在不使用
.AsImplementedInterfaces()
调用的情况下注册,如下所示

builder.RegisterControllers(typeof(MvcApplication).Assembly).InstancePerRequest();
这将使用类型而不是作为接口(
MyProject.controllers.HomeController
而不是
System.Web.Mvc.IController
)将控制器放入Autofac

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

[Export]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : PluginController
而不是这个

[Export(typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : PluginController
请注意
导出
属性中的差异

接下来,我将当前的
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;
    }
}
公共类MyControllerFactory:DefaultControllerFactory
{
专用只读IContainer\u容器;
公共PortalController工厂(IContainer容器)
{
_容器=容器;
}
公共覆盖IController CreateController(System.Web.Routing.RequestContext RequestContext,string controllerName)
{
类型controllerType=GetControllerType(requestContext,controllerName);
如果(controllerType==null)
{
抛出新的HttpException(404,ErrorMessages.Http404);
}
ipluginplugin=PluginManager.Current.GetPlugin(controllerType);
if(plugin!=null&&plugin.Status!=Common.Enums.PluginStatus.Enabled)
{
//控制器/插件已禁用,因此请修改路由数据并返回控制器
路由数据=新路由数据();
data.Values.Add(“控制器”、“插件”);
数据。值。添加(“操作”、“禁用”);
data.Values.Add(“plugin”,plugin.Name);
requestContext.RouteData=数据;
返回ViewRenderer.CreateController(数据);
}
var控制器=((AutofacDependencyResolver)DependencyResolver.Current).RequestLifetimeScope.Resolve(controllerType);
返回控制器作为i控制器;
}
}

当您使用
.AsImplementedInterfaces
时,您的意思是,对于每个具体类型,Autofac为每个接口实现注册此类型

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

尝试呼叫容器。解决问题并查看结果

如果您有:

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

    }
}

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


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

因此,当我使用
asimplementedInterface
时,代码不起作用,因为DefaultControllerFactory抱怨控制器上没有空构造函数。stacktrace甚至没有任何与Autofac相关的内容。这一切都源于DefaultControllerFactory。这让我觉得使用IController与AutofacDependencyResolver不太好。我认为您需要自定义ControllerFactory。如果创建自定义ControllerFactory并注册到IControllerFactory,则可以使其工作,因为您已经将DependencyResolver设置为Autofac。看看能不能帮上忙。我想我得这么做。我认为AutofacDependencyResolver应该解决这个问题,但我想不是。谢谢
  public class Home2Controller : BaseController
{
    public Home2Controller(IPlugin plugin)
    {

    }
}