You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core 3.0自定义IServiceProvider无法解析服务问题排查

问题分析与解决方案:MEF1与.NET Core 3.0 DI整合异常

问题背景

我正尝试将MEF1与.NET Core 3.0的DI框架整合,目标是优先使用MEF1解析服务,若MEF1无法解析则回退到默认DI。但目前遇到异常:自定义MefServiceProvider的GetService()方法仅在解析IConfiguration和IHost时被调用,IForecastService的解析并未触发该方法,看起来默认DI仍在直接处理请求。

现有实现代码

MefServiceProviderFactory

public class MefServiceProviderFactory : IServiceProviderFactory<IDependencyResolver>
{
    private ServiceProvider m_defaultServiceProvider;

    public IDependencyResolver CreateBuilder(IServiceCollection services)
    {
        m_defaultServiceProvider = services.BuildServiceProvider();
        MefDependencyResolver.Initialize(AppContext.BaseDirectory);
        return DependencyResolver.Instance;
    }

    public IServiceProvider CreateServiceProvider(IDependencyResolver resolver) =>
        new MefServiceProvider(resolver, m_defaultServiceProvider);
}

MefServiceProvider

public class MefServiceProvider : IServiceProvider
{
    private readonly IDependencyResolver m_resolver;
    private readonly ServiceProvider m_defaultServiceProvider;

    public MefServiceProvider(IDependencyResolver resolver, ServiceProvider defaultServiceProvider)
    {
        m_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
        m_defaultServiceProvider = defaultServiceProvider ?? throw new ArgumentNullException(nameof(defaultServiceProvider));
    }

    public object GetService(Type serviceType) =>
        m_defaultServiceProvider.GetService(serviceType) ?? m_resolver.GetInstanceOrNull(serviceType);
}

服务注册

services.AddTransient<IForecastService, ForecastService>();

Program.cs配置

public static IHostBuilder CreateHostBuilder(string[] args) => Host
            .CreateDefaultBuilder(args)
            .UseServiceProviderFactory(new MefServiceProviderFactory())
            .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>());

问题原因

  1. 提前构建默认容器导致解析短路:在MefServiceProviderFactory.CreateBuilder中直接调用services.BuildServiceProvider(),会提前将所有已注册服务(包括IForecastService)绑定到默认DI容器。后续框架解析服务时,默认容器已能直接处理请求,不会经过自定义MefServiceProvider。
  2. 解析顺序与目标相反:当前GetService逻辑是先查默认DI、再查MEF,完全违背了“优先MEF”的需求。

解决方案

1. 修正MefServiceProviderFactory实现

不要提前构建默认容器,保留IServiceCollection并在创建自定义容器时延迟构建默认DI:

public class MefServiceProviderFactory : IServiceProviderFactory<IServiceCollection>
{
    public IServiceCollection CreateBuilder(IServiceCollection services)
    {
        // 仅初始化MEF,不提前构建默认容器
        MefDependencyResolver.Initialize(AppContext.BaseDirectory);
        return services;
    }

    public IServiceProvider CreateServiceProvider(IServiceCollection containerBuilder)
    {
        // 构建默认ServiceProvider,作为自定义容器的依赖
        var defaultProvider = containerBuilder.BuildServiceProvider();
        return new MefServiceProvider(DependencyResolver.Instance, defaultProvider);
    }
}

2. 调整MefServiceProvider解析顺序(优先MEF)

把解析逻辑改为先尝试MEF,失败再回退默认DI:

public class MefServiceProvider : IServiceProvider
{
    private readonly IDependencyResolver m_resolver;
    private readonly IServiceProvider m_defaultServiceProvider;

    public MefServiceProvider(IDependencyResolver resolver, IServiceProvider defaultServiceProvider)
    {
        m_resolver = resolver ?? throw new ArgumentNullException(nameof(resolver));
        m_defaultServiceProvider = defaultServiceProvider ?? throw new ArgumentNullException(nameof(defaultServiceProvider));
    }

    public object GetService(Type serviceType)
    {
        // 优先使用MEF解析
        var mefInstance = m_resolver.GetInstanceOrNull(serviceType);
        if (mefInstance != null)
            return mefInstance;
        
        // MEF解析失败,回退到默认DI
        return m_defaultServiceProvider.GetService(serviceType);
    }
}

3. 确保MEF正确注册服务

确认服务实现类已通过MEF特性标记,且MEF扫描目录包含目标程序集:

[Export(typeof(IForecastService))]
public class ForecastService : IForecastService
{
    // 服务实现逻辑
}

内容的提问来源于stack exchange,提问作者MajidH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:13:11