【问题标题】:Error using WebApi and MEF: Make sure that the controller has a parameterless public constructor使用 WebApi 和 MEF 时出错:确保控制器具有无参数的公共构造函数
【发布时间】:2015-01-28 13:38:48
【问题描述】:

我在 VS 2012 中使用 MEF、WebAPI。

我收到错误

"exceptionMessage":"尝试创建类型为 'ClienteController' 的控制器时发生错误。请确保控制器 有一个无参数的公共 构造函数。","exceptionType":"System.InvalidOperationException"

我在 Global.asax.cs 中有:

public class WebApiApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

        AggregateCatalog catalog = new AggregateCatalog();
        catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
        CompositionContainer container = MEFLoader.Init(catalog.Catalogs);
        DependencyResolver.SetResolver(new MefDependencyResolver(container)); // view controllers
        GlobalConfiguration.Configuration.DependencyResolver = new MefAPIDependencyResolver(container); // web api controllers

    }

在我的 MEFLoader 类中

    public static CompositionContainer Init(ICollection<ComposablePartCatalog> catalogParts)
    {
        var catalog = new AggregateCatalog();

        catalog.Catalogs.Add(new AssemblyCatalog(typeof(BuscadorClient).Assembly));
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(Core.DataRepositoryFactory).Assembly));
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(Comun.DataContract.BusinessFault).Assembly));

        if (catalogParts != null)
            foreach (var part in catalogParts)
                catalog.Catalogs.Add(part);

        var container = new CompositionContainer(catalog);
        return container;
    }

Assemblies 在 Webapi 应用程序网站的 bin 文件夹中,在集成环境中。

注意事项:

在开发环境中,本地开发,有时会失败,解决方案是“重新编译”WebApi App Project (csproj)

无论如何,在集成环境中失败了。

Microsoft.Internal.Collections.WeakReferenceCollection1.&lt;CleanupDeadReferences&gt;b__0(WeakReference w)\r\n at System.Collections.Generic.List1.RemoveAll(Predicate1 match)\r\n at Microsoft.Internal.Collections.WeakReferenceCollection1.Add(T item)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.StartSatisfyingImports(PartManager partManager, AtomicComposition atomicComposition )\r\n 在 System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImports(PartManager partManager, ComposablePart part, Boolean shouldTrackImports)\r\n 在 System.ComponentModel.Composition.Hosting.ImportEngine.SatisfyImports(ComposablePart 部分)\r\n n 在 System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine 引擎,ComposablePart 部分,ExportDefinition 定义)\r\n 在 System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportedValue(CatalogPart 部分,ExportDefinition 导出,布尔 isSharedPart)\ r\n 在 System.ComponentModel.Composition.Primitives.Export.get_Value()\r\n 在 System.ComponentModel.Composition.ReflectionModel.ImportingItem.CastS ingleExportToImportType(类型类型,导出导出)\r\n 在 System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.SetImport(ImportingItem 项,Export[] 导出)\r\n 在 System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.SetImport( ImportDefinition 定义,IEnumerable1 exports)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.PartManager.TrySetImport(ImportDefinition import, Export[] exports)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImportSubset(PartManager partManager, IEnumerable1 导入,AtomicComposition atomicComposition)\r\n 在 System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImportsStateMachine(PartManager partManager, ComposablePart part)\r\n 在 System.ComponentModel.Composition.Hosting.ImportEngine .TrySatisfyImports(PartManager partManager, ComposablePart part, Boolean shouldTrackImports)\r\n 在 System.ComponentModel.Composition.Hosting.ImportEngine.SatisfyImports(ComposablePart 部分)\r\n 在 System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine引擎、ComposablePart 部件、ExportDefinition 定义)\r\n 在 System.ComponentModel.Composition.Hosting.Cat alogExportProvider.GetExportedValue(CatalogPart part, ExportDefinition export, Boolean isSharedPart)\r\n 在 System.ComponentModel.Composition.Primitives.Export.get_Value()\r\n 在 COMPANY..Core.MefExtensions.GetExportedValueByType(CompositionContainer 容器,类型类型) 在

【问题讨论】:

  • 多线程可能有问题
  • 我建议将 YifanLu 的答案标记为正确。与 ASP.NET 控制器一起使用时,MEF 会莫名其妙地呕吐,唯一的线索是在 WeakReferenceCollection 清理中。容器必须被实例化为线程安全的。

标签: asp.net-web-api mef asp.net-web-api2


【解决方案1】:

不确定是否有人仍然对答案感兴趣,但我在使用 MEF 作为 IoC 的 WebApi 服务中遇到了同样的问题。组合容器在启动时使用自定义导出提供程序列表创建。

我的问题的原因是导出提供程序不是使用thread safe constructor 创建的。

在这种情况下,除了在创建 CompositionContainer 时设置线程安全选项外,您还应该使用将 thread safe 设置为 true 的构造函数创建所有自定义导出提供程序。

var aggregate = new AggregateCatalog(assemblyCatalogs);
//create default export provider to be thread safe
var defaultExportProvider = new CatalogExportProvider(aggregate, true);
_compContainer = new CompositionContainer(CompositionOptions.DisableSilentRejection|CompositionOptions.IsThreadSafe, defaultExportProvider);
defaultExportProvider.SourceProvider = _compContainer;

【讨论】:

  • 当然对答案感兴趣(因此赞成)。使用 WPF (Prism) 和 MEF 和多线程,并且出现了奇怪的行为。在引导程序中实现的这个块使它一切都消失了。谢谢。
猜你喜欢
  • 1970-01-01
  • 2016-03-31
  • 1970-01-01
  • 1970-01-01
  • 2014-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
相关资源
最近更新 更多