MVC MEF错误:确保控制器具有无参数的公共构造函数

问题描述 投票:0回答:1

对于使用MEF的MVC应用程序,有时我会收到错误“”

我有一个.NET解决方案

  1. 一个MVC Web应用程序项目,
  2. 许多类库项目负责身份验证,获取配置,进行外部API调用等。

我已经通过代码配置了如下所示的MEF,并使用IIS在Web服务器上部署了它。几次观察到下面的错误,之后我试图多次加载页面,但它仍然会抛出相同的错误。

刷新应用程序池后,只有错误消失。我一直在努力调试和理解错误,但没有成功。我在哪里错误配置MEF?

enter image description here

Global.asax中:

public class Global : HttpApplication
  {
    void Application_Start(object sender, EventArgs e)
    {
      AreaRegistration.RegisterAllAreas();
      GlobalConfiguration.Configure(WebApiConfig.Register);
      RouteConfig.RegisterRoutes(RouteTable.Routes);

      var pluginFolders = LoadMefComponents();
      Bootstrapper.Compose(pluginFolders);
      IControllerFactory mefControllerFactory = new MefControllerFactory(Bootstrapper.Container);
      ControllerBuilder.Current.SetControllerFactory(mefControllerFactory);
    }

    protected List<string> LoadMefComponents()
    {
      var pluginFolders = new List<string>();
      string ModulesPath = CommonUtility.GetApplicationDirectory();
      var plugins = Directory.GetDirectories(ModulesPath).ToList();
      plugins.ForEach(path =>
      {
        var directoryInfo = new DirectoryInfo(path);
        pluginFolders.Add(directoryInfo.Name);
      });
      return pluginFolders;
    }
  }

MEFControllerFactory.cs:此文件驻留在App_Start中

public class MefControllerFactory : DefaultControllerFactory
    {
        private readonly CompositionContainer _container;
        private readonly Dictionary<IController, Lazy<object, object>> exports;
        private readonly object syncRoot;

        public MefControllerFactory(CompositionContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            this._container = container;
            this.exports = new Dictionary<IController, Lazy<object, object>>();
            this.syncRoot = new object();

        }

        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            Lazy<object, object> export = _container.GetExports(controllerType, null, null).FirstOrDefault();

            var controller = null == export ? base.GetControllerInstance(requestContext, controllerType)
                                : (IController)export.Value;
            lock (this.syncRoot)
            {
                this.exports.Add(controller, export);
            }
            return controller;
        }

        public override void ReleaseController(IController controller)
        {
            lock (this.syncRoot)
            {
                var export = this.exports[controller];
                this.exports.Remove(controller);
               // this._container.ReleaseExport(export);
            }
            ((IDisposable)controller).Dispose();
        }
    }

Bootstrapper.cs:此文件驻留在App_Start中

public class Bootstrapper
    {
        private static CompositionContainer compositionContainer;
        private static bool IsLoaded = false;

        public static CompositionContainer Container
        {
            get { return compositionContainer; }
            set { compositionContainer = value; }
        }

        public static void Compose(List<string> pluginFolders)
        {
            if (IsLoaded) return;
            var catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            catalog.Catalogs.Add(new DirectoryCatalog(CommonUtility.GetApplicationDirectory()));
            compositionContainer = new CompositionContainer(catalog);
            compositionContainer.ComposeParts();
            IsLoaded = true;
        }

        public static T GetInstance<T>(string contractName = null)
        {
            var type = default(T);
            if (compositionContainer == null) return type;
            if (!string.IsNullOrWhiteSpace(contractName))
                type = compositionContainer.GetExportedValue<T>(contractName);
            else
                type = compositionContainer.GetExportedValue<T>();
            return type;
        }
    }

CommonUtility.cs:此文件驻留在App_Start中

public class CommonUtility
    {

        public static string GetApplicationDirectory()
        {
            string codeBase = Assembly.GetExecutingAssembly().CodeBase;
            UriBuilder uri = new UriBuilder(codeBase);
            string path = Uri.UnescapeDataString(uri.Path);
            return Path.GetDirectoryName(path);

        }
    }

HomeController.cs:

[CommonExceptionFilter]
  public class HomeController : Controller
  {
    private IConfigurationManager _configurationManager;

    [ImportingConstructor]
    public HomeController()
    {
      _configurationManager = Bootstrapper.GetInstance<IConfigurationManager>();
    }

    public async Task<ActionResult> Index()
    {
      //Business Logic
      return View()

    }
  }

IConfigurationManager.cs

[InheritedExport]
    public interface IConfigurationManager
    {
        string GetConfigurationValue(string keyName)
    }

ConfigurationManager.cs

[PartCreationPolicy(CreationPolicy.Shared)]
    public class ConfigurationManager: IConfigurationManager
    {
        [ImportingConstructor]
        public ConfigurationManager()
        {

        }

        public string GetConfigurationValue(string keyName)
        {
            return "";
        }
    }

在MVC项目中使用的IHttpHandlers:

public class CommonServiceHandler : HttpTaskAsyncHandler, IRequiresSessionState
  {
    private ICommonServiceHandlerManager _commonServiceHandlerManager;


    public CommonServiceHandler()
    {
      _commonServiceHandlerManager = Bootstrapper.GetInstance<ICommonServiceHandlerManager>();
    }


    public override bool IsReusable
    {
      get
      {
        return false;
      }
    }

  }
c# model-view-controller mef
1个回答
1
投票

此错误表示至少存在一个控制器,其构造函数参数未解析。 每个控制器都需要在运行时解析构造函数。默认情况下,每个c#类都有一个默认(无参数)构造函数,可以在需要创建类的实例时调用它。 但是,在定义显式构造函数后,您将丢失默认构造函数,因此,您需要确保所有控制器都具有无参数构造函数,或者如果它们具有参数构造函数,则需要通过依赖项注入来注册参数。

© www.soinside.com 2019 - 2024. All rights reserved.