使用Autofac控制工作单元/存储库模式中的数据依赖性

时间:2017-09-10 16:50:30

标签: c# constructor autofac repository-pattern unit-of-work

这应该很容易解释,但我不确定如何将解决方案应用到我的DI容器(Autofac)中。

我有一个存储库

public class ClientRepository
{
    public ClientRepository(MyContext context)
    {

    }
}

然后是工作单位

public class UnitOfWork
{
    public UnitOfWork(MyContext context, ClientRepository repository)
    {

    }
}

工作单元/存储库模式规定将工作单元实例化的DataContext应传递到存储库的构造函数中,这样一切都使用相同的DataContext

换句话说,AutoFac应该基本上应该这样做......

MyContext context = new MyContext();
ClientRepository clientRepository = new ClientRepository(context);
UnitOfWork unitOfWork = new UnitOfWork(context, clientRepository);

如何告诉Autofac正确连接?

回应Cyril关于使用Func> ...

的评论

我有一个“ClientService”类需要这些UnitOfWorks中的一个或多个。在下面的示例中,“添加”和“删除”的工作单元之间不应存在依赖关系共享(除非我已将依赖关系注册为Singleton)。如果我不使用Func&gt ;,例如单独的范围,我怎么能实现这种分离?

public class ClientService
{
    private readonly Func<Owned<UnitOfWork>> _unitOfWorkFactory;

    public ClientService(Func<Owned<UnitOfWork>> unitOfWorkFactory)
    {
        _unitOfWorkFactory = unitOfWorkFactory;
    }

    public AddClients(Clients c)
    {
        using(var uoc = _unitOfWorkFactory())
        {

        }
    }

    public DeleteClients(Clients C)
    {
        using(var uoc = _unitOfWorkFactory())
        {

        }
    }
}

1 个答案:

答案 0 :(得分:-1)

使Autofac基本上能满足您的需求:

  1. 创建容器
  2. 在容器中注册所需的所有模块
  3. 在该模块中注册所需的所有类型
  4. 在Global.asax.cs中设置DependencyResolver
  5. 请参阅用法示例(mvc)
  6. 所以

    1. 创建容器
    2.     public static class DependencyContainer
          {
              internal static IContainer Container;
      
              public static IContainer CreateContainer(Assembly assembly)
              {
                  var builder = new ContainerBuilder();
                  builder.RegisterControllers(assembly);
      
                  IModule[] modules =
                  {
                      //You don't have to create lots of modules...
                      //but it would be better to have different modules for different application layers
                      new DataModule( /*some params if you need*/),
                      new DataAccessModule( ),
                      //new BusinessLogicModule(),
                      //...
                  };
      
                  foreach (var module in modules)
                  {
                      builder.RegisterModule(module);
                  }
      
                  return Container;
              }        
          }
      

      2-3。实现容器和寄存器类型中使用的模块

      DataModule的:

      internal class DataModule : Module
      {
          protected override void Load(ContainerBuilder builder)
          {
              //When you specify InstancePerRequest it means that everything (resolved via this DI) 
              //is using the same DataContext for current request
              builder.RegisterType<MyContext>().As<MyContext>().InstancePerRequest();
          }
      }
      

      DataAccessModule:

      internal class DataAccessModule : Module
      {
          protected override void Load(ContainerBuilder builder)
          {
              builder.RegisterType<UnitOfWork>().As<UnitOfWork>().InstancePerRequest();
              builder.RegisterType<ClientRepository>().As<ClientRepository>().InstancePerRequest();
              //if you are using generic repository you can register all them in one line like this: 
              //builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerRequest();
          }
      }
      
      1. 在Global.asax.cs中设置DependencyResolver

        public class MvcApplication : HttpApplication
        {
            protected void Application_Start()
            {
                //Default Application_Start() content       
                //...
        
                //Using our DI
                var container = DependencyContainer.CreateContainer(typeof(MvcApplication).Assembly);
                DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            }
        }
        
      2. 用法示例

        public class MyController : Controller
        {
            private readonly UnitOfWork _unitOfWork;
            private readonly ClientRepository _clientRepository;
        
            public MyController(UnitOfWork unitOfWork, ClientRepository clientRepository)
            {
                _unitOfWork = unitOfWork;
                _clientRepository = clientRepository;
            }
        
            //When you are calling action DoSomething, you don't have to worry about constructor params (DI will pass them)
            public ActionResult DoSomething()
            {
                _clientRepository.DoSomething();
        
                return PartialView("DoSomething");
            }
        }