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

借助Autofac委托工厂简化装饰器注册,规避依赖变更修改

解决Autofac装饰器依赖变更时频繁修改注册代码的问题

嘿,我太懂你这种烦恼了——每次给装饰器加个新依赖,就得跑到Autofac注册代码里手动加c.Resolve<XXX>(),改来改去不仅麻烦,还容易漏加。幸好Autofac的委托工厂机制正好能解决这个问题,让我们把注册代码改成一劳永逸的版本!

当前的麻烦写法

先看看你现在可能在使用的注册方式,每次FooDecorator的构造函数新增依赖(比如加个IXyz),就得手动在装饰器注册里加c.Resolve<IXyz>():

[TestFixture]
internal sealed class AutofacRegistrationTests
{
    [Test]
    public void CurrentWayToRegisterDecorator()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<Foo>().As<IFoo>();
        builder.RegisterType<Xyz>().As<IXyz>();

        // 每次FooDecorator加新依赖,这里必须手动修改
        builder.RegisterDecorator((c, inner) => 
            new FooDecorator(inner, c.Resolve<IXyz>()), 
            typeof(IFoo));

        using var container = builder.Build();
        var foo = container.Resolve<IFoo>();
        Assert.IsInstanceOf<FooDecorator>(foo);
    }
}

public interface IFoo { }
public class Foo : IFoo { }
public interface IXyz { }
public class Xyz : IXyz { }
public class FooDecorator : IFoo
{
    public FooDecorator(IFoo inner, IXyz xyz)
    {
        // 业务逻辑
    }
}

用Autofac委托工厂实现无需修改的注册

Autofac的委托工厂可以让容器自动解析装饰器的所有依赖,不用我们手动写一堆Resolve。核心思路是定义一个工厂委托,让Autofac自动实现这个委托,然后用它来创建装饰器。

步骤1:定义装饰器的工厂委托

先给你的装饰器定义一个工厂委托,参数是被装饰的原始实例(IFoo),返回装饰器实例:

// 工厂委托:传入被装饰的IFoo,返回装饰后的FooDecorator
public delegate IFoo FooDecoratorFactory(IFoo inner);

步骤2:注册工厂和装饰器

接下来的注册就很清爽了——先注册装饰器本身(让Autofac管理它的所有依赖),然后让Autofac自动生成工厂委托的实现,最后用这个工厂来注册装饰器:

[TestFixture]
internal sealed class AutofacRegistrationTests
{
    [Test]
    public void DesiredWayToRegisterDecorator()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<Foo>().As<IFoo>();
        builder.RegisterType<Xyz>().As<IXyz>();
        
        // 注册装饰器,Autofac会自动处理它的所有依赖
        builder.RegisterType<FooDecorator>();
        // 让Autofac自动实现我们定义的工厂委托
        builder.RegisterGeneratedFactory<FooDecoratorFactory>();

        // 用工厂创建装饰器,再也不用手动Resolve任何依赖了!
        builder.RegisterDecorator((c, inner) => 
            c.Resolve<FooDecoratorFactory>().Invoke(inner), 
            typeof(IFoo));

        using var container = builder.Build();
        var foo = container.Resolve<IFoo>();
        Assert.IsInstanceOf<FooDecorator>(foo);
    }
}

为什么这能解决问题?

  • 以后不管你给FooDecorator加多少新依赖(比如再加个IAbc),只需要给装饰器的构造函数加对应参数,然后注册IAbc的实现就行,完全不用碰装饰器的注册代码。
  • RegisterGeneratedFactory会让Autofac自动生成工厂委托的实现,这个工厂会帮你自动解析装饰器需要的所有依赖——包括你后来新增的那些。

额外优化:泛型装饰器的适配

如果你的装饰器是泛型的(比如FooDecorator<T> : IFoo<T>),同样可以用这个方案,只需要定义泛型工厂委托:

public delegate IFoo<T> FooDecoratorFactory<T>(IFoo<T> inner);

注册的时候用RegisterGeneratedFactory<FooDecoratorFactory<>>()(注意泛型的写法),装饰器的注册逻辑完全不用改动,一样能自动适配所有泛型参数的依赖。

这样一来,你就彻底摆脱了每次修改装饰器依赖就得调整注册代码的麻烦,实现了真正的“一次注册,终身受用”!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 12:21:38