WebApi和MEF出现错误:确保控制器具有无参公共构造函数

3

我在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;
    }

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

注意:

在开发环境、本地开发中,有时会出现失败的情况,解决方案是“重新编译”WebApi App项目(csproj)。

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

Microsoft.Internal.Collections.WeakReferenceCollection<code>1.<CleanupDeadReferences>b__0(WeakReference w)\r\n at System.Collections.Generic.List</code>1.RemoveAll(Predicate<code>1 match)\r\n at Microsoft.Internal.Collections.WeakReferenceCollection</code>1.Add(T item)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.StartSatisfyingImports(PartManager partManager, AtomicComposition atomicComposition)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImports(PartManager partManager, ComposablePart part, Boolean shouldTrackImports)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.SatisfyImports(ComposablePart part)\r\n at System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine engine, ComposablePart part, ExportDefinition definition)\r\n at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportedValue(CatalogPart part, ExportDefinition export, Boolean isSharedPart)\r\n at System.ComponentModel.Composition.Primitives.Export.get_Value()\r\n at System.ComponentModel.Composition.ReflectionModel.ImportingItem.CastSingleExportToImportType(Type type, Export export)\r\n at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.SetImport(ImportingItem item, Export[] exports)\r\n at System.ComponentModel.Composition.ReflectionModel.ReflectionComposablePart.SetImport(ImportDefinition definition, IEnumerable<code>1 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, IEnumerable</code>1 imports, AtomicComposition atomicComposition)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImportsStateMachine(PartManager partManager, ComposablePart part)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.TrySatisfyImports(PartManager partManager, ComposablePart part, Boolean shouldTrackImports)\r\n at System.ComponentModel.Composition.Hosting.ImportEngine.SatisfyImports(ComposablePart part)\r\n at System.ComponentModel.Composition.Hosting.CompositionServices.GetExportedValueFromComposedPart(ImportEngine engine, ComposablePart part, ExportDefinition definition)\r\n at System.ComponentModel.Composition.Hosting.CatalogExportProvider.GetExportedValue(CatalogPart part, ExportDefinition export, Boolean isSharedPart)\r\n at System.ComponentModel.Composition.Primitives.Export.get_Value()\r\n at COMPANY..Core.MefExtensions.GetExportedValueByType(CompositionContainer container, Type type) in


1
可能与多线程有关的问题。 - Kiquenet
我建议将YifanLu的答案标记为正确。当与ASP.NET控制器一起使用时,MEF会出现莫名其妙的错误,并且唯一的线索在于WeakReferenceCollection清理中。容器必须被实例化为线程安全。 - tomo
1个回答

6

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

我的问题的原因是导出提供程序未使用线程安全构造函数创建。

在这种情况下,除了在创建CompositionContainer时设置线程安全选项外,您还应该使用将线程安全设置为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以及多线程时,出现了奇怪的行为。在引导程序中实现这个nugget后,所有问题都消失了。谢谢。 - Duncan Howe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接