gpt4 book ai didi

domain-driven-design - DDD 中的工厂、服务、存储库

转载 作者:行者123 更新时间:2023-12-04 08:23:12 24 4
gpt4 key购买 nike

我对 DDD 中的factoriesrepositoriesservices 有一些疑问。我有以下实体:文件夹、文件、FileData。

在我看来,“文件夹”是一个聚合根,应该负责创建 File 和 FileData 对象。

所以我的第一个问题是我应该使用 factory 来创建这个聚合还是由 repository 决定?此时我有 2 个存储库,一个用于文件夹,另一个用于文件,但在我看来,我应该将它们合并在一起。以下代码片段显示了我的 Folder Repository,它位于我的基础架构层中:

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
}

总结一下:我是否应该使用该服务来创建文件夹对象。或者服务应该只使用一个工厂,它负责创建对象并将创建的对象发送到存储库?服务中的依赖注入(inject)怎么样,我应该使用 Unity 等 IOC 容器从 UI 层注入(inject)我的服务,还是应该只对服务中的依赖项进行硬编码?

谢谢

最佳答案

So my first question is should I use a factory to create this aggregate or is it up to the repository?

工厂负责创建,而存储库负责持久性。重构后,存储库将有效地创建实例。然而,这个创建过程通常是通过反射完成的,并且不会通过工厂来防止应该只在创建时发生的初始化。

At this time I have 2 repositories, one for Folder and another for File, but it seems to me I should merge them together.

在 DDD 中,每个聚合都有一个存储库。该存储库将负责持久化作为聚合一部分的所有实体和值对象。

I have my doubts about the location of the service. Should it be moved to the domain layer?

IMO,一个应用服务可以被放置到领域层,因为它已经作为一个门面,将它们放在一起会带来凝聚力的好处。关于 IoService 的一种想法是,诸如 AddFile 之类的方法通常会通过聚合标识而不是实例来参数化。由于应用程序服务已经引用了一个存储库,它可以根据需要加载适当的聚合。否则,调用代码将负责调用存储库。

Should I use the service for creating the folder object. Or should the service just use a factory, which have the responsibility of creating the object and send the created object to the repository?

IoService 看起来不错,除了前面的评论是通过身份而不是实例来参数化。

What about dependency injection in the service, should I inject my services from the UI layer with IOC containers like Unity or should I just hardcode the dependencies in the service?

这是一个偏好问题。如果您可以从使用 IoC 容器中受益,请使用它。但是,不要仅仅为了使用它而使用它。您已经在进行依赖注入(inject),只是没有花哨的 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();
}

在此示例中,更多的行为被委托(delegate)给文件夹聚合和文件实体。应用程序服务简单地调用聚合上的适当方法。

关于domain-driven-design - DDD 中的工厂、服务、存储库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15218583/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com