我在理解存储库域对象关系时遇到了一些问题。以下是我对域名设计所了解的一些信息(它们也可能是错误的或不准确的)。考虑到这些,我找不到从存储库中获取域对象的方法。
在DDD中,域名应该只知道并包含业务所需的内容,其他所有内容都必须从域中清除。没关系。而且,从任何企业抽象数据访问也是一种很好的做法。应用程序不需要知道我们存储数据的位置或存储数据的方式。我们只要求存储库给我们一个域对象,它为我们提供了我们想要的对象,或者其他方式也是有效的,我们给存储库一个域对象并将它发送到存储。
在面向对象设计中声明域对象的公共setter也是一种非常糟糕的方法,因为我们无法控制谁访问了什么并改变了什么。因此,最好只公开对象外部所需的内容。
因此,在我的脑海中,我无法找到实现我的存储库的方法。我可以在我的代码中使用任何ORM或纯sql并检索数据。
但我无法从持久性对象创建域对象;
任何帮助将不胜感激......
答案 0 :(得分:4)
您有以下选项:
<强> 1。 ORM可以使用私有字段。
据我所知,ORM(例如Entity Framework,NHibernate)可以通过非公开的设置者设置属性。
有一个例子可以证明它适用于实体框架 - Entity Framework, Private Constructors and Private Setters。
如果你使用NHibernate,你的setter应该是public/protected virtual
/ protected internal virtual
或private
支持字段。您可以在Property Access strategies in NHibernate SO问题中找到更多信息。
<强> 2。可以使用Reflection。
它也可用于访问私有字段/属性。 It is possible to set private property via reflection
第3。使用公共构造函数构建实体并不是一种坏习惯。
声明包含所有字段的公共构造函数似乎不正确。我可能有几个模型要填写,这意味着我必须使用不同的参数集定义几个构造函数。
您的域实体只需要一个公共构造函数,其中包含完整的属性列表。尽管有几个模型可以填充,但只有一个构造函数就足够了。存储库负责调用构造函数并将模型映射到其参数中。
修改强>
<强> 4。可以使用Automapper。
以下测试表明AutoMapper可以通过私有设置器映射属性。
[TestClass]
public class AutomapperTest
{
[TestMethod]
public void Test()
{
// arrange
Mapper.CreateMap<AModel, A>();
var model = new AModel { Value = 100 };
//act
var entity = Mapper.Map<A>(model);
// assert
entity.Value.Should().Be(100);
entity.Value.Should().Be(model.Value);
}
}
public class AModel
{
public int Value { get; set; }
}
public class A
{
public int Value { get; private set; }
}
答案 1 :(得分:1)
不能使用ORM没有公共设置器来创建域对象。如果您正在使用实体框架,它肯定可以在模型第一种方法中映射私有属性,并且您只需要在代码优先方法中使用公共 getters 。我不知道其他ORM-s。
答案 2 :(得分:0)
我想在这里了解您的查询。关于如何进行的一些提示。 首先,域应该知道存储库合同而不是实际的存储库基础结构。换句话说,你可以选择有3个类库,如下所示
现在由您来决定使用依赖注入将XYZSQLRepository注入XYZDomain的位置。
如果需要,您还可以尝试使用事件模型来注册这些存储库。
使用自定义服务定位器获取具体对象