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

如何使用Autofac.Extras.DynamicProxy为Blazor组件生命周期实现AOP日志

实现方案

核心原理

Blazor框架提供了IComponentFactory接口作为组件实例的创建入口,替换默认实现后即可自定义组件实例的解析逻辑,完全保留原生Razor组件的编写和引用语法,无需调整原有组件的调用方式。

前置依赖

需提前安装对应Nuget包:

  • Autofac.Extensions.DependencyInjection
  • Autofac.Extras.DynamicProxy
  • Castle.Core

步骤1:实现日志拦截器

public class LoggingInterceptor : IInterceptor
{
    private readonly ConcurrentDictionary<Type, ConcurrentDictionary<string, int>> _invokeCounters = new();

    public void Intercept(IInvocation invocation)
    {
        var componentType = invocation.TargetType;
        var methodName = invocation.Method.Name;

        // 统计方法调用次数
        var typeCounters = _invokeCounters.GetOrAdd(componentType, _ => new ConcurrentDictionary<string, int>());
        var count = typeCounters.AddOrUpdate(methodName, 1, (_, old) => old + 1);

        // 拼接日志内容,自动获取参数值
        var args = string.Join(", ", invocation.Arguments.Select((arg, idx) => $"{invocation.Method.GetParameters()[idx].Name}: {arg}"));
        Console.WriteLine($"[{count}]{componentType.Name}.{methodName}({args})");

        // 执行原有方法逻辑
        invocation.Proceed();
    }
}

步骤2:实现自定义组件工厂

public class AutofacComponentFactory : IComponentFactory
{
    private readonly ILifetimeScope _lifetimeScope;

    public AutofacComponentFactory(ILifetimeScope lifetimeScope)
    {
        _lifetimeScope = lifetimeScope;
    }

    public IComponent CreateInstance(IServiceProvider serviceProvider, Type componentType)
    {
        // 从Autofac容器解析带代理的组件实例
        return (IComponent)_lifetimeScope.Resolve(componentType);
    }
}

步骤3:服务注册配置

public class Program
{
    public static async Task Main(string[] args)
    {
        var builder = WebAssemblyHostBuilder.CreateDefault(args);
        builder.RootComponents.Add<App>("#app");

        // 替换Blazor默认的组件工厂
        builder.Services.AddScoped<IComponentFactory, AutofacComponentFactory>();

        // 接入Autofac容器
        builder.Host.UseAutofac(ConfigureContainer);

        var host = builder.Build();
        await host.RunAsync();
    }

    private static void ConfigureContainer(ContainerBuilder builder)
    {
        // 注册拦截器
        builder.RegisterType<LoggingInterceptor>().AsSelf();

        // 注册需要日志埋点的组件,启用动态代理
        builder.RegisterType<BasicChild>()
            .AsSelf()
            .EnableClassInterceptors() // Blazor组件为类,直接用类代理即可
            .InterceptedBy(typeof(LoggingInterceptor))
            .InstancePerDependency(); // 保持Blazor组件默认瞬态生命周期
    }
}

步骤4:清理组件代码

最终组件完全不需要嵌入日志逻辑,保持原生写法即可:

<p>@nameof(BasicChild)</p>
<button @onclick="OnClick">StateHasChanged</button>

@code {
    private void OnClick()
    {
        StateHasChanged();
    }
}

效果说明

所有组件的生命周期方法、用户自定义事件方法都会被拦截器自动捕获并输出日志,完全不需要修改组件的调用方式,原生Blazor语法不受任何影响。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 11:15:03