借助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
相关产品推荐
相关产品推荐

