将工作单元从服务或回购中解耦

本文关键字:解耦 服务 工作 单元 | 更新日期: 2023-09-27 18:01:49

我正在尝试将我的工作单元与我的服务或存储库解耦,这样每当我想添加一个新服务时,我就不必触摸UoW代码。我该怎么做呢?

_categoryService = _unitOfWork.Get<ICategoryService>();

所以不用

_unitOfWork.CategoryService.Add(category)

我可以说;

_categoryService.Add(category);

将工作单元从服务或回购中解耦

我正在尝试将我的工作单元与我的服务或解耦存储库,这样我就不必在我希望的时候触摸UoW代码添加新服务

嗯,这是一个好的开始!: -)

我提出的解决方案不是唯一可行的解决方案,有几个很好的方法来实现UoW(谷歌会帮助你)。但这应该给你一个大的画面。

首先,创建2个接口:IUnitOfWork和IRepository

public interface IUnitOfWork : System.IDisposable
{
  IRepository<TEntity> GetRepository<TEntity>() where TEntity : class;
  void Save();
}
public interface IRepository<T> : IDisposable where T : class
{
  void Add(T entity);
  void Delete(T entity);
  void Update(T entity);
  T GetById(long Id);
  IEnumerable<T> All();
  IEnumerable<T> AllReadOnly();
  IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
} 

实现非常简单(为了可读性,我删除了所有注释,但不要忘记添加您的注释;-))

public class UnitOfWork<TContext> : IUnitOfWork where TContext : IDbContext, new()
{
  private readonly IDbContext _ctx;
  private Dictionary<Type, object> _repositories;
  private bool _disposed;
  public UnitOfWork()
  {
    _ctx            = new TContext();
    _repositories   = new Dictionary<Type, object>();
    _disposed       = false;
  }
  public IRepository<TEntity> GetRepository<TEntity>() where TEntity : class
  {
    if (_repositories.Keys.Contains(typeof(TEntity)))
      return _repositories[typeof(TEntity)] as IRepository<TEntity>;
    var repository = new Repository<TEntity>(_ctx);
    _repositories.Add(typeof(TEntity), repository);
    return repository;
  }
  public void Save()
  {
     try
     {
       _ctx.SaveChanges();
     }
     catch (DbUpdateConcurrencyException ex)
     {
       ex.Entries.First().Reload();
     }
  }
  …
}
public class Repository<T> : IRepository<T> where T : class
{
  private readonly IDbContext _context;
  private readonly IDbSet<T> _dbset;
  public Repository(IDbContext context)
  {
    _context = context;
    _dbset   = context.Set<T>();
  }
  public virtual void Add(T entity)
  {
    _dbset.Add(entity);
  }
  public virtual void Delete(T entity)
  {
    var entry = _context.Entry(entity);
    entry.State = EntityState.Deleted;
  }
  public virtual void Update(T entity)
  {
    var entry = _context.Entry(entity);
    _dbset.Attach(entity);
    entry.State = EntityState.Modified;
  }
  public virtual T GetById(long id)
  {
    return _dbset.Find(id);
  }
  public virtual IEnumerable<T> All()
  {
    return _dbset.ToList();
  }
  public virtual IEnumerable<T> AllReadOnly()
  {
    return _dbset.AsNoTracking().ToList();
  }
  public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
  {
    return _dbset.Where(predicate);
  }
}

可以看到,两个实现都使用了IDbContext接口。这个接口只是为了方便测试的目的:

public interface IDbContext
{
  DbSet<T> Set<T>() where T : class;
  DbEntityEntry<T> Entry<T>(T entity) where T : class;
  int SaveChanges();
  void Dispose();
}

(如你所见,我使用的是EntityFramework Code First)

现在整个管道都设置好了,让我们来看看如何在服务中使用它。我有一个基本服务,看起来像这样:

internal class Service<T> where T : class
{
  internal Service(Infrastructure.IUnitOfWork uow)
  {
    _repository = uow.GetRepository<T>();
  }
  protected Infrastructure.IRepository<T> Repository
  {
    get { return _repository; }
  }
  private readonly Infrastructure.IRepository<T> _repository;
}

我的所有服务都继承自这个基本服务。

internal class CustomerService : Service<Model.Customer>
{
  internal CustomerService(Infrastructure.IUnitOfWork uow) : base(uow)
  {   
  }
  internal void Add(Model.Customer customer)
  {
    Repository.Add(customer);
  }
  internal Model.Customer GetByID(int id)
  {
    return Repository.Find(c => c.CustomerId == id);
  }
}

就是这样!

现在,如果您想在facade方法或其他地方向多个服务共享相同的UoW,它可以看起来像这样:

using (var uow = new UnitOfWork<CompanyContext>())
{
  var catService = new Services.CategoryService(uow);
  var custService = new Services.CustomerService(uow);
  var cat = new Model.Category { Name = catName };
  catService.Add(dep);
  custService.Add(new Model.Customer { Name = custName, Category = cat });
  uow.Save();
}

希望这对你有帮助!