使用反射对通用存储库进行通用包装



我试图在n层架构中实践松耦合和分离所有内容,但我坚持我所相信的基本内容。我的第一个问题是推荐信。我不断地在程序集之间移动类,因为类A需要类B,但无法到达它,所以让我们移动类B——然后我打破类c。

这是我能想出的最好的办法了。

步骤1:架构

项目。数据

  • 实体(略)

项目。DataAccess

    <
  • 上下文/gh><
  • 迁移/gh><
  • 存储库/gh>
  • 工作单位
  • 视图模型

项目。Web

    <
  • 控制器/gh>

步骤2:使用Project。数据访问作为表示和数据之间的粘合剂

我正在使用工作单元模式,但这需要访问poco,所以我不能在控制器中使用UoW。因此,我认为创建名为ViewModelService的包装器/服务将是一个很好的计划。这个服务实例化了UoW,并将automap Viewmodels返回给我的控制器。

然而…

我的UoW/Repository模式是通用的,所以我想让我的服务也通用。

<标题> IRepository h1> public interface IRepository<TObject> { IQueryable<TObject> All(); IQueryable<TObject> Filter(Expression<Func<TObject, bool>> predicate); IQueryable<TObject> Filter<TKey>(Expression<Func<TObject, bool>> filter, out int total, int index = 0, int size = 50); bool Contains(Expression<Func<TObject, bool>> predicate); TObject Find(params object[] keys); TObject Find(Expression<Func<TObject, bool>> predicate); TObject Create(TObject t); int Delete(TObject t); int Delete(Expression<Func<TObject, bool>> predicate); int Update(TObject t); void Ignore(TObject t); int Count { get; } } <标题>通用BaseRepository h1> public class BaseRepository<TObject> : IRepository<TObject> where TObject : class { protected AppDbContext Context = null; public BaseRepository(AppDbContext context) { Context = context; } protected DbSet<TObject> DbSet { get { return Context.Set<TObject>(); } } public virtual int Count { get { return Queryable.Count<TObject>(DbSet); } } // ... (You get the picture) } <标题> UnitOfWork h1> public class UnitOfWork : IDisposable { private readonly AppDbContext _context = new AppDbContext(); private BaseRepository<Order> _orderRepository; private BaseRepository<Product> _productRepository; private BaseRepository<ApplicationUser> _userRepository; private bool _disposed; public BaseRepository<Order> OrderRepository { get { if (_orderRepository == null) { _orderRepository = new BaseRepository<Order>(_context); } return _orderRepository; } } public BaseRepository<Product> ProductRepository { get { if (_productRepository == null) { _productRepository = new BaseRepository<Product>(_context); } return _productRepository; } } public BaseRepository<ApplicationUser> UserRepository { get { if (_userRepository == null) { _userRepository = new BaseRepository<ApplicationUser>(_context); } return _userRepository; } } public void Dispose() { Dispose(true); GC.SuppressFinalize(this); } public void Save() { _context.SaveChanges(); } protected virtual void Dispose(bool disposing) { if (!_disposed) { if (disposing) { _context.Dispose(); } } _disposed = true; } }

所以现在-没有"service"和新的n层-我在我的控制器中使用它。

 public class ProductController : Controller
{
    private UnitOfWork _unitOfWork = new UnitOfWork();
    // GET: /Product/
    [Route]
    public ActionResult Index()
    {
        var model = _unitOfWork.ProductRepository.All();
        return View(model);
    }
// Etc...

但是现在我把所有东西都分成了单独的层,我不能那样做了。我不想让我的Unit of Work类映射ViewModels

下面是我创建这个"服务"的尝试(甚至不确定它的名字是否正确):

<标题> ViewModelService h1> public class ViewModelService : IViewModelService { private readonly UnitOfWork _unitOfWork = new UnitOfWork(); public T GetSingle<T>(int key) { // Get appropriate repository based on T1? throw new System.NotImplementedException(); } public IQueryable<T> GetAll<T>() { throw new System.NotImplementedException(); } }

现在我面临的问题是——我如何确保当我调用:

_viewModelService.GetSingle<ProductVM>(id);

它自己(通过反射?)计算出它应该调用:

_unitOfWork.ProductRepository.Find(id)

在仓库内部吗?

哇,我觉得我解释得很糟糕!:)

TL;博士

我有一个UnitOfWork类:

 public class UnitOfWork : IDisposable
{
    private readonly DbContext _context = new DbContext();
    private BaseRepository<Order> _orderRepository;
    private BaseRepository<Product> _productRepository;
    private BaseRepository<ApplicationUser> _userRepository;
    private bool _disposed;
    public BaseRepository<Order> OrderRepository
    {
        get
        {
            if (_orderRepository == null)
            {
                _orderRepository = new BaseRepository<Order>(_context);
            }
            return _orderRepository;
        }
    }
    public BaseRepository<Product> ProductRepository
    {
        get
        {
            if (_productRepository == null)
            {
                _productRepository = new BaseRepository<Product>(_context);
            }
            return _productRepository;
        }
    }
    public BaseRepository<ApplicationUser> UserRepository
    {
        get
        {
            if (_userRepository == null)
            {
                _userRepository = new BaseRepository<ApplicationUser>(_context);
            }
            return _userRepository;
        }
    }
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    public void Save()
    {
        _context.SaveChanges();
    }
    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                _context.Dispose();
            }
        }
        _disposed = true;
    }
}
现在我想创建一个通用包装器:

public class ViewModelService : IViewModelService
{
    private readonly UnitOfWork _unitOfWork = new UnitOfWork();
    public T GetSingle<T>(int key)
    {
        // Get appropriate repository based on T1?
        throw new System.NotImplementedException();
    }
}

我如何使用反射,以便当我请求GetSingle<ProductVM>(id)时,包装器将其转换为对_unitOfWork.ProductRepository.Find(id);的调用-因此包装器知道在UoW中调用正确的存储库。

方法之一是拥有一个通用的抽象类,并让具体的子类覆盖提供实际存储库的特定部分。这样,大部分代码都可以放在抽象类中,并且仍然可以精确地提供子类级别所需的内容。

 // two generic types
 // TDTO - view model type
 // TDomain - domain type
 public abstract class AbstractViewModelService<TDTO, TDomain> : IViewModelService
 {
     private UnitOfWork _uow { get; }        
     public AbstractViewModelService( UnitOfWork uow )
     {
         this._uow = uow;
     }
     public abstract IRepository<TDomain> Repository { get; }
     public TDTO GetSingle<TDTO>(int key)
     {
         // Get appropriate repository based on T1?
         // it is here ->
         return Mapper.DynamicMap<TDTO>( this.Repository.Find( key ) );
     }
 }
 public class UserViewModelService : AbstractViewModelService<UserDto, User> 
 {
     public override IRepository<User> Repository
     {
         get
         {
             return this._uow.UserRepository;
         }
     }
     ...
 }
 public class AccountViewModelService : AbstractViewModelService<AccountDto, Account> 
 {
     public override IRepository<Account> Repository
     {
         get
         {
             return this._uow.AccountRepository;
         }
     }
     ...
 }

为什么不使用MEF?打破您的UOW,它将组成存储库-您还将受益于您将不会有重复的

get
    {
        if (_productRepository == null)
        {
            _productRepository = new BaseRepository<Product>(_context);
        }
        return _productRepository;
    }

为每个导出项添加元数据,然后在

 public T GetSingle<T>(int key)
{
    // Get appropriate repository based on T1?
    throw new System.NotImplementedException();
}

你可以根据它暴露的元数据得到正确的插件。或者您可以将所有存储库添加到ServiceLoactor中,这样您就可以编写而不是

_unitOfWork.ProductRepository.Find(id);
ServiceLocator.Current.GetInstance<T>().find(id)

相关内容

  • 没有找到相关文章

最新更新