3

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

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

public interface IRepository
{
   IEnumerable<SomeObject> Get();
}

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

我有一个缓存的实现,它将检查缓存,如果没有找到,请调用 db 存储库。这被传递给构造函数:

[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 中模仿这种行为?

4

1 回答 1

0

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

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)));

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

于 2013-08-13T08:05:09.810 回答