5

我在理解存储库域对象关系时遇到了一些小问题。以下是我所了解的关于域名设计的一些信息(它们也可能是错误的或不准确的)。考虑到这些,我找不到从存储库获取域对象的方法。如何从存储库中检索域对象

在DDD中,域应该只知道和包含业务所需要的内容,其他所有内容都必须从域中清除。没关系。并且从任何业务中抽象数据访问也是一个很好的做法。应用程序不需要知道我们存储数据的位置或我们如何存储数据。我们只要求存储库给我们一个域对象,它给了我们我们想要的对象或者另一种方式也是有效的,我们给存储库一个域对象并将它发送到存储器。

为面向对象声明公共setter对于面向对象的设计来说也是一个非常糟糕的方法,因为我们将无法控制谁正在访问什么并更改什么。因此,只公开需要在对象外部需要的东西是一种很好的做法。

因此,在我的脑海中,我无法想出实现我的存储库的方法。我可以在我的代码中使用任何ORM或纯SQL,并检索数据。

但我无法从持久对象创建域对象;

  1. 由于他们没有公共setter,我不能创建和设置字段值。
  2. 声明包含所有字段的公共构造函数看起来不正确。我可能需要填写几个模型,这意味着我必须定义几个具有不同参数集的构造函数。

任何帮助将不胜感激...

回答

4

有你有选择:

1奥姆斯可以与私人领域的合作。

据我所知,ORMs(例如Entity Framework,NHibernate)可以通过非公共设置者设置属性。

有,证明它的实体框架的例子 - Entity Framework, Private Constructors and Private Setters

如果您使用NHibernate,您的setter应该是public/protected virtual/protected internal virtualprivate支持字段可以使用。您可以在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

感谢您的提示。但是我读过一篇提到领域模型和持久性模型的文章是两个不同的集合,我认为这是正确的。在我目前的项目中,有一个非常糟糕的db-first设计,它是域逻辑的完全灾难。这就是为什么我不想使用我的EF实体。所以我需要一个更好的方式表达所需域的独立域类集。我的问题是;我如何从EF实体中获取数据到我的域对象,这些对象不公开公共属性? HTTP://www.sapiensworks。com/blog/post/2012/04/20/Dont-Use-ORM-Entities-To-Model-The-Domain.aspx – ayk

+0

您的存储库(特定数据映射器)可负责将EF实体映射到域实体。我可以使用单个公共构造函数来构建域实体。还有一点提示 - 你的映射器可能类似于Builder或Factory模式。 –

+0

如果您要手动绘制地图,那么请考虑彻底删除EF模型,因为它只会减慢速度。您的存储库可以使用普通的DataReader。 –

0

我想在这里了解您的查询。关于如何继续的一些提示。 首先,域应该知道存储库合同,而不是实际的存储库基础结构。换句话说,你可以选择有3类库如下

  1. XYZDomain(会知道XYZRepository,并在此接口的适当 方法调用)
  2. XYZRepository(包含接口IXYZService接口)
  3. XYZSQLRepository(XYZRepository接口的实际实现)。

现在,您可以选择使用依赖注入将XYZSQLRepository注入XYZDomain的位置。

如果需要,您还可以尝试使用事件模型来注册这些存储库。

使用自定义服务定位器,以获得具体的对象

+0

首先,感谢您的评论。但是在这里,我对解耦组件的细节不感兴趣。我只是徘徊如何才能获得一个对象公开没有字段,并期望它从存储库中加载.. – ayk

+1

我希望你同意业务逻辑或你的域换句话说应该是不可知的基础设施。如果我正确理解你,你正在尝试创建能反弹域对象而不是其他方式的存储库。我的观点是,业务不需要在下面进行更改(例如,ORM更改为不同的内容)。您的存储库的职责是使用域类的**公共方法**来设置域。所以如果你正在寻找如何设置值,那么它将使用域方法。希望你知道为什么它是方法而不是setters – Lin

1

这不是真的,你不能创建没有公共setter方法ORM域对象。如果您使用的是实体框架,它绝对可以在模型第一种方法中映射私有属性,并且您只需要使用代码第一种方法公开获取获取者。我不知道其他ORM-s如何。

相关问题