我对 DDD 中的工厂,存储库和服务有一些疑问。我有以下实体:文件夹,文件,FileData。
在我看来,“文件夹”是聚合根,应该负责创建File和FileData对象。
所以我的第一个问题是我应该使用工厂来创建此聚合,还是由存储库决定?这时我有2个存储库,一个用于Folder,另一个用于File,但在我看来,我应该将它们合并在一起。以下代码段显示了我的文件夹存储库,它位于我的基础架构层中:
public class FolderRepository : IFolderRepository
{
#region Fields
private readonly IFolderContext _context;
private readonly IUnitOfWork _unitOfWork;
#endregion
#region Constructor
public FolderRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
_context = _unitOfWork.Context as IFolderContext;
}
#endregion
public IUnitOfWork UnitOfWork
{
get { return _unitOfWork; }
}
public IQueryable<Folder> All
{
get { return _context.Folders; }
}
public Folder Find(Guid id)
{
return _context.Folders.Find(id);
}
public void InsertGraph(Folder entity)
{
_context.Folders.Add(entity);
}
public void InsertOrUpdate(Folder entity)
{
if (entity.Id == Guid.Empty)
{
_context.SetAdd(entity);
}
else
{
_context.SetModified(entity);
}
}
public bool Delete(Guid id)
{
var folder = this.Find(id) ?? _context.Folders.Find(id);
_context.Folders.Remove(folder);
return folder == null;
}
public int AmountOfFilesIncluded(Folder folder)
{
throw new NotImplementedException();
//return folder.Files.Count();
}
public void Dispose()
{
_context.Dispose();
}
}
接下来,我在应用程序层中创建了一项服务,这称为“IoService”。我怀疑服务的位置。是应该将其移至域层?
public class IoService : IIoService
{
#region Fields
private readonly IFolderRepository _folderRepository;
private readonly IFileRepository _fileRepository;
private readonly IUserReferenceRepository _userReferenceRepository;
#endregion
#region Constructor
public IoService(IFolderRepository folderRepository, IFileRepository fileRepository, IUserReferenceRepository userReferenceRepository)
{
if(folderRepository == null)
throw new NullReferenceException("folderRepository");
if(fileRepository == null)
throw new NullReferenceException("fileRepository");
if (userReferenceRepository == null)
throw new NullReferenceException("userReferenceRepository");
_folderRepository = folderRepository;
_fileRepository = fileRepository;
_userReferenceRepository = userReferenceRepository;
}
#endregion
#region Folder Methods
/// <summary>
/// Create a new 'Folder'
/// </summary>
/// <param name="userReference"></param>
/// <param name="name"></param>
/// <param name="parentFolder"></param>
/// <param name="userIds">The given users represent who have access to the folder</param>
/// <param name="keywords"></param>
/// <param name="share"></param>
public void AddFolder(UserReference userReference, string name, Folder parentFolder = null, IList<Guid> userIds = null, IEnumerable<string> keywords = null, bool share = false)
{
var userReferenceList = new List<UserReference> { userReference };
if (userIds != null && userIds.Any())
{
userReferenceList.AddRange(userIds.Select(id => _userReferenceRepository.Find(id)));
}
var folder = new Folder
{
Name = name,
ParentFolder = parentFolder,
Shared = share,
Deleted = false,
CreatedBy = userReference,
UserReferences = userReferenceList
};
if (keywords != null)
{
folder.Keywords = keywords.Select(keyword =>
new Keyword
{
Folder = folder,
Type = "web",
Value = keyword,
}).ToList();
}
//insert into repository
_folderRepository.InsertOrUpdate(folder);
//save
_folderRepository.UnitOfWork.Save();
}
/// <summary>
/// Get 'Folder' by it's id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public Folder GetFolder(Guid id)
{
return _folderRepository.Find(id);
}
#endregion
#region File Methods
/// <summary>
/// Add a new 'File'
/// </summary>
/// <param name="userReference"></param>
/// <param name="folder"></param>
/// <param name="data"></param>
/// <param name="name"></param>
/// <param name="title"></param>
/// <param name="keywords"></param>
/// <param name="shared"></param>
public void AddFile(UserReference userReference, Folder folder, FileData data, string name, string title = "", IEnumerable<string> keywords = null, bool shared = false)
{
var file = new File
{
Name = name,
Folder = folder,
FileData = data,
CreatedBy = userReference,
Type = data.Type
};
if (keywords != null)
{
file.Keywords = keywords.Select(keyword =>
new Keyword
{
File = file,
Type = "web",
Value = keyword,
}).ToList();
}
folder.Files.Add(file);
folder.Updated = DateTime.UtcNow;
_folderRepository.InsertOrUpdate(folder);
//save
_folderRepository.UnitOfWork.Save();
}
/// <summary>
/// Get 'File' by it's id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public File GetFile(Guid id)
{
return _fileRepository.Find(id);
}
#endregion
}
总结一下: 我应该使用该服务来创建文件夹对象。或者服务应该只使用工厂,它负责创建对象并将创建的对象发送到存储库?那么服务中的依赖注入怎么样,我应该从UI层注入我的服务和IOC容器,比如 Unity ,还是我应该硬编码服务中的依赖项?
由于