Repository Pattern工作单元依赖注入Ninject



我在体系结构中使用存储库、工作单元和依赖项注入模式我的分层:

核心

数据层

BusinessLayer

ServiceLayer

我的结构有问题,以以上的工作班为单位

   public class UnitOfWork:IUnitOfWork
{
    private readonly IDataContext _context;
    private IKullaniciDal _kullaniciDal;
    private IKategoriDal _kategoriDal;
    private IUrunDal _urunDal;
    public UnitOfWork(IDataContext context)
    {
        _context = context;
    }
    public IKategoriDal KategoriDal => _kategoriDal ?? (_kategoriDal = new KategoriDal(_context));
    public IKullaniciDal KullaniciDal => _kullaniciDal ?? (_kullaniciDal =  new KullaniciDal(_context));
    public IUrunDal UrunDal => _urunDal ?? (_urunDal = new UrunDal(_context));
    public void SaveChanges()
    {
        _context.SaveChanges();
    }
}

在这里,我想注入像_kullaniciDAL 这样的DataAccessLayers

搜索了很多,我看到了一些生成存储库的示例,但我不想直接从业务访问存储库实例,我想访问我的KullaniciDal类的实例这是KullaniciDal 的代码

 public interface IKullaniciDal : IRepositoryEntityFramework<Kullanici>
{
}
public class KullaniciDal : RepositoryEntityFramework<Kullanici>, IKullaniciDal
{
    public KullaniciDal(IDataContext dbContextBase) : base(dbContextBase)
   {
   }
}

我想给数据访问层写一些额外的函数,特别是其中的一些函数,并想将这些实例作为工作单元的一部分

如何注入Dal类?请注意,我将上下文对象传递给每个dal类

我在这里看到了几个问题。

首先,你的UoW正在更新DAL本身,而不是让DI注入它。如果你要走DI路由,最好让DI注入所有内容,让它自己管理对象的范围等。一般来说,如果您发现自己在基础结构类中使用new(),请退一步考虑注入它

public class UnitOfWork:IUnitOfWork
{
    private readonly IDataContext _context;
    public UnitOfWork(IDataContext context,IKullaniciDal kullaniciDal,IKategoriDal kategoriDal, IUrunDal urunDal)
    {
        KullaniciDal = kullaniciDal;
        KategoriDal = kategoriDal;
        UrunDal = urunDal;
        _context = context;
    }
    public IKategoriDal KategoriDal{get;private set;}
    public IKullaniciDal KullaniciDal{get;private set;}
    public IUrunDal UrunDal{get;private set;}
    public void SaveChanges()
    {
        _context.SaveChanges();
    }
}

下一个问题更像是一个设计问题。为什么UoW需要所有这些DAL?我自己也觉得奇怪。

如果我正在实现一个需要控制UoW和DAL的业务层,我会简单地将它们注入业务层。

public class FooBLL
{
    private IKullanicDal _kullanicDal;
    private IUnitOfWork _unitOfWork;
    public FooBLL(IKullanicDal kullanicDal,IUnitOfWork unitOfWork)
    {
        _kullanicDal = kullanicDal;
        _unitOfWork = unitOfWork;
    }
    public void FooBusinessMethod()
    {
      _unitOfWork.Begin();
      //do something with dal
      //_unitOfWork.Commit etc
    }
}

的确,当使用诸如EF之类的ORM时,存储库/dll和工作单元都需要上下文,但它们是独立的模式。我会允许你的DI容器适当地确定你的上下文、UoW、BLL等的范围,你不需要担心传递依赖关系,让容器为你做这项工作。

这也有其他SOLID设计的好处。考虑一下您是否正在实现一个http过滤器,该过滤器可以通过http会话自动提交您的uow。过滤器只需要知道IUnitOfWork方法提交、回滚等。它应该取决于最小接口,不需要知道DAL。

我发现了另一种在需要时即时创建存储库的解决方案。它还支持多个数据上下文,还有一点是IUnitOfWork接口继承了IDisposable。该代码适用于EF Core v2.0。这是所有UnitOfWork.cs类代码:

public class UnitOfWork<TContext> : IUnitOfWork<TContext> where TContext : DbContext
{
    private Dictionary<string, dynamic> _repositories;
    private DbContext _context;
    public UnitOfWork(TContext context)
    {
        _context = context ?? throw new ArgumentNullException(nameof(context));
    }
    public IRepository<TEntity> Repository<TEntity>() where TEntity : class, IEntity, new()
    {
        if (_repositories == null)
        {
            _repositories = new Dictionary<string, dynamic>();
        }
        var type = typeof(TEntity).Name;
        if (_repositories.ContainsKey(type))
        {
            return (IRepository<TEntity>)_repositories[type];
        }
        _repositories.Add(type, Activator.CreateInstance(typeof(RepositoryEntityFramework<TEntity>), _context));
        return _repositories[type];
    }
    public void SaveChanges()
    {
        _context.SaveChanges();
    }
    public void BeginTransaction(System.Data.IsolationLevel isolationLevel = System.Data.IsolationLevel.ReadCommitted)
    {
        _context.Database.BeginTransaction();
    }
    public bool Commit()
    {
        _context.Database.CommitTransaction();
        return true;
    }
    public void Rollback()
    {
        _context.Database.RollbackTransaction();
    }
    /// <inheritdoc />
    /// <summary>
    /// Disposes the current object
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    /// <summary>
    /// Disposes all external resources.
    /// </summary>
    /// <param name="disposing">The dispose indicator.</param>
    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
    }
}

最新更新