【发布时间】:2014-03-22 19:51:46
【问题描述】:
我正在尝试在 n 层架构中练习松散耦合和分离所有内容,但我坚持 - 我相信 - 基本的东西。我的第一个问题是参考。我经常在程序集之间移动类,因为 A 类需要 B 类,但无法到达它,所以让我们移动 B 类——然后我打破 C 类。
这是我能想到的最好的了。
第 1 步:架构
Project.Data
- 实体 (POCO)
Project.DataAccess
- 上下文
- 迁移
- 存储库
- 工作单元
- 视图模型
Project.Web
- 控制器
- 观看次数
第 2 步:使用 Project.DataAccess 作为 Presentation 和 Data 之间的粘合剂
我正在使用工作单元模式,但这需要访问 POCO,因此我无法在控制器中使用 UoW。因此,我认为创建名为ViewModelService 的包装器/服务是一个不错的计划。此服务实例化 UoW 并将 AutoMapped Viewmodels 返回到我的控制器。
然而……
我的 UoW/Repository 模式是通用的,所以我也在尝试使我的服务也通用。
IRepository
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
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)
}
工作单位
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;
}
}
所以现在 - 没有“服务”和新的 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 类来映射 ViewModel。
这是我创建这个“服务”的尝试(甚至不确定它的正确名称):
ViewModelService
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;DR
我有一个 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();
}
}
如何使用 reflection 以便当我请求 GetSingle<ProductVM>(id) 时,包装器会将其转换为对 _unitOfWork.ProductRepository.Find(id); 的调用——因此包装器知道调用 UoW 内的正确存储库.
哇哦。
【问题讨论】:
-
也许你可以创建类似
unitOfWork.GetRepository<ProductVM>()的东西,它将创建所需的类型化存储库。然后在 GetSingle 方法中,您将使用存储库实例,并将 id 保存到本地字典?
标签: c# generics design-patterns reflection n-tier-architecture