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

使用MethodBoundaryAspect.Fody时,如何从IServiceCollection/DI获取服务?

解决MethodBoundaryAspect.Fody无法从DI获取服务的问题

核心问题在于MethodBoundaryAspect.Fody默认是编译时直接实例化切面类,不会通过DI容器创建,所以常规的构造/属性注入无法生效。以下是两种可行的解决方案:

方案1:自定义AspectFactory让切面由DI管理(推荐)

利用Fody的扩展能力,让切面实例从DI容器中获取,完全符合依赖注入原则:

  • 实现IAspectFactory接口,通过DI容器创建切面实例

    public class DiAspectFactory : IAspectFactory
    {
        private readonly IServiceProvider _serviceProvider;
    
        public DiAspectFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }
    
        public IAspect CreateAspect(Type aspectType)
        {
            return (IAspect)_serviceProvider.GetRequiredService(aspectType);
        }
    }
    
  • 在程序启动时注册切面和自定义工厂,并配置Fody使用该工厂

    var services = new ServiceCollection();
    // 注册你的切面类,生命周期匹配目标类即可
    services.AddScoped<MyBusinessAspect>();
    // 注册自定义工厂
    services.AddSingleton<IAspectFactory>(provider => new DiAspectFactory(provider));
    
    // 初始化Fody的切面工厂
    var serviceProvider = services.BuildServiceProvider();
    Aspect.Factory = serviceProvider.GetRequiredService<IAspectFactory>();
    
  • 切面类直接使用构造注入

    public class MyBusinessAspect : OnMethodBoundaryAspect
    {
        private readonly IMyDependencyService _dependencyService;
    
        public MyBusinessAspect(IMyDependencyService dependencyService)
        {
            _dependencyService = dependencyService;
        }
    
        public override void OnEntry(MethodExecutionArgs args)
        {
            // 直接使用注入的服务
            _dependencyService.Execute(args.Method.Name);
        }
    }
    

方案2:静态服务定位器(应急方案)

如果暂时无法修改切面创建逻辑,可以用静态类持有IServiceProvider,但要注意测试隔离和线程安全:

  • 创建静态定位器类

    public static class ServiceLocator
    {
        public static IServiceProvider? Instance { get; set; }
    
        public static T GetRequiredService<T>() where T : notnull
        {
            return Instance?.GetRequiredService<T>() ?? 
                throw new InvalidOperationException("ServiceLocator未初始化");
        }
    }
    
  • 程序启动时初始化

    var serviceProvider = services.BuildServiceProvider();
    ServiceLocator.Instance = serviceProvider;
    
  • 切面中调用获取服务

    public class MyBusinessAspect : OnMethodBoundaryAspect
    {
        public override void OnExit(MethodExecutionArgs args)
        {
            var logger = ServiceLocator.GetRequiredService<ILogger<MyBusinessAspect>>();
            logger.LogInformation("方法 {Method} 执行完成", args.Method.Name);
        }
    }
    

注意事项

  • 方案1更适合长期维护,切面生命周期由DI管理,便于单元测试时替换依赖
  • 方案2尽量避免在大型项目中使用,静态实例会带来全局状态,增加测试难度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 10:08:17