3

我有一個關於工廠服務DDD一些問題。我有以下實體:文件夾,文件,FileData。工廠,服務,資源庫在DDD

在我看來,「文件夾」是聚合根,應該有創建File和FileData對象的責任。

所以我的第一個問題是,我應該使用工廠創建此aggreate或者是它的?此時我有兩個存儲庫,一個用於文件夾,另一個用於文件,但在我看來,我應該將它們合併在一起。下面的代碼片段,顯示了我文件夾存儲庫,它位於我的基礎設施層:

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或者我應該只是硬編碼服務中的依賴項?

感謝

回答

6

所以我的第一個問題是我應該使用一個工廠來創建此聚合 還是到倉庫?

工廠負責創建,而存儲庫負責持久性。重構後,存儲庫將有效地創建實例。然而,這個創建過程通常是通過反射來完成的,並且不會通過工廠來防止初始化,而這應該只在創建時纔會發生。

這時我有2個倉庫,一個文件夾,另一個用於 文件,但在我看來,我應該一起合併。

在DDD中,您將擁有每個聚合的存儲庫。該存儲庫將負責持久化屬於聚合的一部分的所有實體和值對象。

我對服務的位置有懷疑。是否應將 移至域圖層?

IMO,一個應用服務可以放置到域層,因爲它已經作爲一個門面,並將它們保持在一起會帶來凝聚力的好處。關於IoService的一個想法是,諸如AddFile的方法通常將通過聚合身份而不是實例來參數化。由於應用程序服務已經引用了一個存儲庫,它可以根據需要加載適當的聚合。否則,調用代碼將負責調用存儲庫。

我應該使用服務來創建文件夾對象。還是應該 服務只使用一個工廠,它有責任創建對象並將創建的對象發送到存儲庫?

IoService看起來不錯,除了之前有關身份而不是實例參數化的評論外。

怎麼樣的服務依賴注入,我應該從IOC容器,如統一或UI層注入我 服務應該我 只是硬編碼在服務的依賴關係?

這是一個偏好問題。如果您可以從使用IoC容器中獲益,請使用它。但是,不要僅僅用它來使用它。你已經在做依賴注入了,只是沒有一個漂亮的IoC容器。

樣品

class File 
{ 
    public File(string name, Folder folder, FileData data, UserReference createdBy, IEnumerable<string> keywords = null) 
    { 
     //... 
    } 
} 

... 

class Folder 
{ 
    public File AddFile(string name, FileData data, UserReference createdBy, IEnumerable<string> keywords = null) 
    { 
     var file = new File(name, this, data, createdBy, keywords) 
     this.Files.Add(file); 
     this.Updated = DateTime.UtcNow; 
     return file; 
    } 
} 

... 

public void AddFile(UserReference userReference, Guid folderId, FileData data, string name, string title = "", IEnumerable<string> keywords = null, bool shared = false) 
{ 
    var folder = _folderRepository.Find(folderId); 
    if (folder == null) 
     throw new Exception(); 

    folder.AddFile(name, data, keywords); 

    _folderRepository.InsertOrUpdate(folder); 
    _folderRepository.UnitOfWork.Save(); 
} 

在這個例子中,更多的行爲被委派到文件夾彙總和文件實體。應用程序服務簡單地調用聚合上合適的方法。

+0

非常感謝您的回覆。你能給我一個關於如何編寫AddFile方法的簡單例子,只是我對這個主題100%清楚。 – John 2013-03-05 18:21:42

+0

非常感謝你,現在它對我來說更加清晰。 – John 2013-03-05 18:36:16

+0

因此,讓我們說你想通過它的ID有一個文件,你需要在文件夾庫中添加一個方法來接收文件? – John 2013-03-06 08:49:03