.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>());
问题原因
- 提前构建默认容器导致解析短路:在
MefServiceProviderFactory.CreateBuilder中直接调用services.BuildServiceProvider(),会提前将所有已注册服务(包括IForecastService)绑定到默认DI容器。后续框架解析服务时,默认容器已能直接处理请求,不会经过自定义MefServiceProvider。 - 解析顺序与目标相反:当前
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
相关产品推荐
相关产品推荐

