我有以下域名模型:
public class Company
{
public int Id { get; private set; }
public string Name { get; private set; }
public BlaBla BlaBla { get; private set; }
...
...
public void ChangeName(string newName)
{
//business logic here
Name = newName;
}
}
我们已经使用Entity Framework实现了存储库模式,它们都运行良好。 对于一个非常特殊的情况(使用遗留数据库),我们需要跳过EF并使用普通的sql查询并自己进行映射。
对于映射,代码(伪代码)如下:
using connection
using command
company = new Company();
while (reader.read())
company.ChangeName(reader["company_name"]);
end while
end using
end using
正如您所看到的那样,公司的所有属性都是“私有集”,因为我们正在练习域驱动设计,因此我们无法编写company.Id = reader [“Id”]并且我们必须使用域方法来“填充“公司对象的属性。
有没有一种优雅的方式来做这件事,比如EF?如何在不创建方法SetId(int id)?
的情况下设置Id属性答案 0 :(得分:0)
您可以使用PropertyInfo
(如下所示):
foreach (PropertyInfo propInfo in theType.GetProperties())
{
for (int i = 0; i < reader.FieldCount; i++)
{
if (reader.GetName(i).Trim().ToLower() == propInfo.Name.Trim().ToLower())
{
object asObj = reader.GetValue(i);
if (asObj is System.DBNull) propInfo.SetValue(thisRow, null, null);
else propInfo.SetValue(thisRow, reader.GetValue(i), null);
}
}
}
类型将是您要将属性映射到的typeof(YourType)
。
答案 1 :(得分:0)
在DDD环境中,创建不是构造函数的任务。每个构造函数都应该被私有或保护以满足DDD。有时,当EF(或其他工具)位于中间时,您必须提供可见的默认构造函数。
如上所述,构造不是构造函数的任务,而是可以使用工厂,甚至更好的builder(后者为您提供更具弹性的对象创建)。比一个更优雅的解决方案可能是:
将SQL查询输出映射到DTO。
public class CompanyDTO
{
public int Id { get; set; }
public string Name { get; set; }
public BlaBla BlaBla { get; set; }
// no trace of business logic here
}
并且在您的检索逻辑中,而不是构建真正的Company
对象,而不是创建相关的DTO并使用其成员作为构建器的参数:
//REPO PSEUDO CODE
using connection
using command
companyDTO = new CompanyDTO();
while (reader.read())
companyDTO.Name = reader["company_name"];
end while
end using
end using
// build your real `Company` object using as parameters the one
// stored in the realted DTO.
company = CompanyBuilder.NewBuilder()
.WithCustomId(companyDTO.id)
.WithRegistryInfo(companyDTO.info1, companyDTO.info2, ....)
.WithOwnerInfo(companyDTO.owner1, ....)
.Build();
return company;
根据您的构造逻辑,您可以考虑摆脱DTO并直接调用构建的可能性。我希望我能正确理解问题。