Autofac:使用工厂代理解析带有可选参数的通用接口

时间:2012-04-04 15:32:46

标签: autofac

我正在尝试使用Autofac执行以下操作:

我有一个单元UnitOfWork:

public class UnitOfWork : IUnitOfWork
  {
  IContext contextA { get; set ;}
  IContext contextB { get; set ;}

  public UnitOfWork(IContext contextA, IContext contextB)
    {
    this.contextA = contextA;
    this.contextB = contextB;
    }

  public void Save()
    {
    this.contextA.Save();
    this.contextB.Save();
    }

  ...
  }

我还有一个泛型类GenericRepo:

public class GenericRepo<T> : IRepo<T>
  {
  private IContext context;

  public GenericRepo(IContext context)
    {
    this.context = context;
    }
  }

不输入接口,但它们就在那里。

然后我有这些代表:

public delegate IUnitOfWork IUnitOfWorkFactory();

public delegate IRepo<T> IRepoFactory<T>(IUnitOfWork unitOfWork = null);

现在的问题是:

我需要能够创建存储库。根据通用存储库的类型,它必须使用不同的上下文。我不希望调用代码必须知道repo使用的是什么上下文,所以我不能将上下文用作参数,它必须是UnitOfWork。

但是因为泛型repo是通用的,它不知道从UnitOfWork获取什么上下文,所以它必须通过它的构造函数而不是UnitOfWork来获取上下文。

此外,有时调用代码不关心UnitOfWork(因为它不需要保存),并且在这种情况下必须动态创建UnitOfWork - 它仍然需要一个来获取其数据

所以我需要这个工作:

public void TestCode(IRepoFactory<TypeA> repoFacA, IRepoFactory<TypeB> repoFacB, IUnitOfWorkFactory uowFactory)
  {
  IRepo<TypeA> repoA = repoFacA(); //repoA has contextA from a new UnitOfWork
  IRepo<TypeB> repoB = repoFacB(); //repoB has contextB from a new (different) UnitOfWork

  IUnitOfWork uow = uowFactory();
  IRepo<TypeA> repoA_2 = repoFacA(uow); //repoA_2 has contextA from uow
  IRepo<TypeB> repoB_2 = repoFacB(uow); //repoB_2 has contextB from uow
  }

换句话说,我需要能够使用参数调用泛型委托,并且根据类型,它需要使用该参数的属性构造一个类。

它还需要在没有参数的情况下工作,在这种情况下,Autofac必须解析并使用参数本身。

有关如何在AutoFac中注册所有这些内容的想法吗?

1 个答案:

答案 0 :(得分:2)

好的,我自己找到了。

这是我注册代表的方式:

      builder.Register((b, p) => new GenericRepo<TypeA>(((((p.First() as ConstantParameter)).Value as UnitOfWork) ?? b.Resolve<IUnitOfWork>()).ContextA)).As<IRepo<TypeA>>();
      builder.Register((b, p) => new GenericRepo<TypeB>(((((p.First() as ConstantParameter)).Value as UnitOfWork) ?? b.Resolve<IUnitOfWork>()).ContextB)).As<IRepo<TypeB>>();

编辑:

或者更好,以第一种方式以通用方式进行:

  builder.RegisterGeneric(typeof(GenericRepository<,>)).WithParameter((pi, icc) => true, (pi, icc) => (((((icc as IInstanceLookup).Parameters.First()) as ConstantParameter).Value as IUnitOfWork) ?? icc.Resolve<IUnitOfWork>()).ContextA).As(typeof(IEntityRepository<,>));

'WithParameter()'的第一个参数必须存在,并且必须返回true。我想如果我想过滤给出的参数,我必须在那里做。

反正。如果您有许多需要ContextA的类型,并且只有一些需要contextB,则可以为A进行通用注册,然后为B添加例外。

关于如何使眼睛更干净或更容易的建议总是受欢迎的: - )