如何将Grace/Ninject的WhenInjectInto逻辑迁移至Autofac?
Grace至Autofac依赖注册迁移方案(替代WhenInjectInto)
业务代码实现
public interface ILocationRepository { Task<Location?> GetByIDAsync(int id); } public class LocationRepositoryProxyCache : BaseProxyCache, ILocationRepository { private readonly ICacheProvider<Location> _cacheProvider; private readonly ILocationRepository _locationRepository; public LocationRepositoryProxyCache(ICacheProvider<Location> cacheProvider, ILocationRepository locationRepository) { _cacheProvider = cacheProvider; _locationRepository = locationRepository; } public Task<Location?> GetByIDAsync(int id) { return _cacheProvider.GetOrSetAsync("CACHE_KEY", () => _locationRepository.GetByIDAsync(id)); } } public class LocationRepository : BaseRepository<Location>, ILocationRepository { public LocationRepository(IMyInterface myAppDb) : base(myAppDb) { } public Task<Location?> GetByIDAsync(int id) { return ...; // 数据库查询逻辑 } }
原Grace注册代码
registrationBlock.Export<LocationRepository>().As<ILocationRepository>().When.InjectedInto<LocationRepositoryProxyCache>(); registrationBlock.Export<LocationRepositoryProxyCache>().As<ILocationRepository>();
Autofac迁移实现
Autofac没有直接的WhenInjectInto方法,但可以通过以下两种方式实现相同逻辑:
方式一:利用注册条件判断目标类型
通过When方法结合解析上下文的TargetType,判断当前注入的目标类型,实现和WhenInjectInto等价的效果:
var builder = new ContainerBuilder(); // 当注入目标是LocationRepositoryProxyCache时,使用真实的LocationRepository builder.RegisterType<LocationRepository>() .As<ILocationRepository>() .When(context => context.TargetType == typeof(LocationRepositoryProxyCache)); // 注册缓存代理作为默认的ILocationRepository实现 builder.RegisterType<LocationRepositoryProxyCache>() .As<ILocationRepository>(); var container = builder.Build();
方式二:使用命名服务(更明确的依赖指向)
通过命名服务区分真实仓库和代理,避免条件判断的潜在歧义,适合复杂依赖场景:
var builder = new ContainerBuilder(); // 注册真实仓库并指定名称 builder.RegisterType<LocationRepository>() .Named<ILocationRepository>("RealLocationRepository"); // 注册缓存代理,构造时明确解析命名的真实仓库 builder.RegisterType<LocationRepositoryProxyCache>() .As<ILocationRepository>() .WithParameter( (parameter, context) => parameter.ParameterType == typeof(ILocationRepository), (parameter, context) => context.ResolveNamed<ILocationRepository>("RealLocationRepository") ); var container = builder.Build();
效果说明
两种方式均能实现:
- 当
LocationRepositoryProxyCache需要注入ILocationRepository时,获取真实的数据库访问实现LocationRepository - 其他依赖
ILocationRepository的地方,默认获取带缓存的代理实现LocationRepositoryProxyCache
内容的提问来源于stack exchange,提问作者avechuche
相关产品推荐
相关产品推荐

