Autofac约束绑定

本文关键字:绑定 约束 Autofac | 更新日期: 2023-09-27 18:27:25

我正在考虑从Ninject转移到Autofac,但很难转换其中一个有用的功能——通过属性进行约束绑定。

我目前有这个接口和实现:

public interface IRepository
{
   IEnumerable<SomeObject> Get();
}
public class DBRepository : IRepository
{
   public IEnumerable<SomeObject> Get()
   {
    // call the database
   }
}

我有一个缓存的实现,它将检查缓存,如果没有发现任何内容,则调用数据库存储库。这被传递到构造函数:

[DataNeeded]
public class CacheRepository : IRepository
{
    private readonly IRepository dataRepo;
    public CacheRepository(IRepository dataRepo)
    {
        this.dataRepo = dataRepo;
    }
    public IEnumerable<SomeObject> Get()
    {
        // check the cache and if nothing found:
        return this.dataRepo.Get();
    }
}

最后,我有一个调用控制器,它将使用缓存来获取一个对象:

[CacheNeeded]
public class HomeController : ApiController
{
    private readonly IRepository cacheRepo;
    public CacheRepository(IRepository cacheRepo)
    {
        this.cacheRepo= cacheRepo;
    }
    public IEnumerable<SomeObject> Get()
    {
       return this.cacheRepo.Get();
    }
}

正如您所看到的,我重用了这个接口,在数据存储库上添加了一个缓存层,这种模式工作起来非常巧妙。然后,我使用了一些自定义属性来告诉Ninject,我需要某种类型的IRepository。配置如下:

kernel.Bind<IRepository>().To<DbRepository>().WhenClassHas<DataNeeded>();
kernel.Bind<IRepository>().To<CacheRepository>().WhenClassHas<CacheNeeded>();

有没有办法在Autofac中模仿这种行为?

Autofac约束绑定

我想不出用Autofac来实现这种机制的任何简洁明了的方法,但也许你可以利用Autofac选择实现的含义之一。我会使用键控服务,在您的情况下是这样的:首先,您需要定义一个枚举,而不是自定义属性

enum RepositoryKind {CacheNeeded, DataNeeded}

然后注册组件,用那些提供缓存或数据功能的组件来标记它们,例如:

  builder.RegisterType<DbRepository>()
         .Keyed<IRepository>(RepositoryKind.CacheNeeded);
  builder.Register(c => new CacheRepository(c.ResolveKeyed<IRepository(RepositoryKind.CacheNeeded)))
         .Keyed<IRepository>(RepositoryKind.DataNeeded);
  builder.Register(c => new HomeController(c.ResolveKeyed<IRepository>(RepositoryKind.DataNeeded)));

这种方法的优点是,您不会在控制器中透露实现细节,也不会在配置中应用缓存。