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

使用Autofac为基接口的所有派生实现配置通用装饰器

问题与解决方案

问题背景

现有类层级结构如下:基接口IBase、抽象基实现BaseImplementation,以及继承自IBase的扩展接口IExtended1、IExtended2及其具体实现类:

public interface IBase
{
    void Execute();
}

public abstract class BaseImplementation : IBase
{
    public virtual void Execute() {
        Console.WriteLine("BaseImplementation: Executing base functionality.");
    }
}

public interface IExtended1 : IBase
{
    void ExtendedFunctionality1();
}

public class ExtendedImplementation1 : BaseImplementation, IExtended1
{
    public void ExtendedFunctionality1()
    {
        Console.WriteLine("ExtendedImplementation1: Executing extended functionality 1.");
    }

    public override void Execute()
    {
        base.Execute();
        Console.WriteLine("ExtendedImplementation1: Overridden base execution.");
    }
}

public interface IExtended2 : IBase
{
    void ExtendedFunctionality2();
}

public class ExtendedImplementation2 : BaseImplementation, IExtended2
{
    public void ExtendedFunctionality2()
    {
        Console.WriteLine("ExtendedImplementation2: Executing extended functionality 2.");
    }

    public override void Execute()
    {
        base.Execute();
        Console.WriteLine("ExtendedImplementation2: Overridden base execution.");
    }
}

希望通过BaseDecorator添加横切逻辑,作用于IBase及其所有实现类:

public class BaseDecorator : IBase
{
    private readonly IBase _inner;

    public BaseDecorator(IBase inner) {
        _inner = inner;
    }

    public void Execute() {
        Console.WriteLine("BaseDecorator: Before execution.");
        _inner.Execute();
        Console.WriteLine("BaseDecorator: After execution.");
    }
}

要求:依赖扩展接口(如IExtended1)的消费者,注入时能获取到被BaseDecorator装饰的具体实现,且无需为新增的每个IExtendedX接口单独创建装饰器。

结论与解决方案

当前的BaseDecorator设计存在类型兼容问题:它仅实现了IBase,无法直接赋值给IExtended1/IExtended2类型(因为装饰器没有实现扩展接口的方法)。但通过Autofac结合动态代理可以完美解决这个需求,无需为每个扩展接口编写单独的装饰器。

具体实现步骤

1. 安装依赖包

首先安装Autofac的动态代理扩展包:

Install-Package Autofac.Extras.DynamicProxy

2. 实现通用拦截器

将原BaseDecorator的横切逻辑改为拦截器实现,自动适配所有继承自IBase的扩展接口:

using Castle.DynamicProxy;

public class BaseExecutionInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        // 仅对IBase的Execute方法添加横切逻辑
        if (invocation.Method == typeof(IBase).GetMethod(nameof(IBase.Execute)))
        {
            Console.WriteLine("BaseDecorator: Before execution.");
            // 执行原方法
            invocation.Proceed();
            Console.WriteLine("BaseDecorator: After execution.");
        }
        else
        {
            // 扩展接口的其他方法直接执行
            invocation.Proceed();
        }
    }
}

3. Autofac注册配置

通过注册启用接口拦截,将拦截器应用到所有IBase的实现类上:

var builder = new ContainerBuilder();

// 注册拦截器
builder.RegisterType<BaseExecutionInterceptor>();

// 注册具体实现类,关联到对应的扩展接口,并启用拦截
builder.RegisterType<ExtendedImplementation1>()
       .As<IExtended1>()
       .EnableInterfaceInterceptors()
       .InterceptedBy(typeof(BaseExecutionInterceptor));

builder.RegisterType<ExtendedImplementation2>()
       .As<IExtended2>()
       .EnableInterfaceInterceptors()
       .InterceptedBy(typeof(BaseExecutionInterceptor));

// 构建容器
var container = builder.Build();

4. 测试验证

当消费者依赖IExtended1时,解析得到的实例会自动被拦截器装饰,执行Execute方法时会触发横切逻辑,同时不影响扩展方法的调用:

var service = container.Resolve<IExtended1>();
service.Execute();
// 输出:
// BaseDecorator: Before execution.
// BaseImplementation: Executing base functionality.
// ExtendedImplementation1: Overridden base execution.
// BaseDecorator: After execution.

service.ExtendedFunctionality1();
// 输出:
// ExtendedImplementation1: Executing extended functionality 1.

补充说明

如果不想使用动态代理,也可以通过泛型装饰器实现,但需要为每个扩展接口单独注册泛型装饰器,这不符合“无需为新增扩展接口单独操作”的要求,因此动态代理方案是更优选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 12:59:55