如何从存储库中检索域对象

时间:2014-01-19 23:56:28

标签: c# domain-driven-design automapper repository-pattern ddd-repositories

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

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

在面向对象设计中声明域对象的公共setter也是一种非常糟糕的方法,因为我们无法控制谁访问了什么并改变了什么。因此,最好只公开对象外部所需的内容。

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

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

  1. 由于他们没有公共设置器,我无​​法创建和设置字段值。
  2. 声明包含所有字段的公共构造函数似乎不正确。我可能有几个模型要填写,这意味着我必须使用不同的参数集定义几个构造函数。
  3. 任何帮助将不胜感激......

3 个答案:

答案 0 :(得分:4)

您有以下选项:

<强> 1。 ORM可以使用私有字段。

据我所知,ORM(例如Entity FrameworkNHibernate)可以通过非公开的设置者设置属性。

有一个例子可以证明它适用于实体框架 - 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 :(得分:1)

不能使用ORM没有公共设置器来创建域对象。如果您正在使用实体框架,它肯定可以在模型第一种方法中映射私有属性,并且您只需要在代码优先方法中使用公共 getters 。我不知道其他ORM-s。

答案 2 :(得分:0)

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

  1. XYZDomain(将知道XYZRepository并调用相应的 这个界面的方法)
  2. XYZRepository(包含接口IXYZService接口)
  3. XYZSQLRepository(XYZRepository接口的实际实现)。
  4. 现在由您来决定使用依赖注入将XYZSQLRepository注入XYZDomain的位置。

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

    使用自定义服务定位器获取具体对象