【问题标题】:Handling collection properties in a class and NHibernate entities处理类和 NHibernate 实体中的集合属性
【发布时间】:2009-11-25 16:15:51
【问题描述】:

我想知道在类中公开集合的推荐方法是什么,以及它与使用 NHibernate 实体时做同样事情的方式是否有任何不同。

让我解释一下...我的类公开集合属性从未遇到过具体问题,例如:

IList<SomeObjType> MyProperty { get; set; }

将 setter 设置为 protected 或 private 有时可以让我更好地控制我想要如何处理集合。 我最近看到了 Davy Brion 的这篇文章:

http://davybrion.com/blog/2009/10/stop-exposing-collections-already/

Davy 明确建议将集合作为 IEnumerables 而不是让我们说 Lists,以禁止用户选择直接操作这些集合的内容。我可以理解他的观点,但我并不完全相信,通过阅读他帖子中的 cmets,我并不是唯一一个。

但是,当涉及到 NHibernate 实体时,以他建议的方式隐藏集合非常有意义,尤其是在级联到位时。我想完全控制会话中的实体及其集合,并且为集合属性公开 AddXxx 和 RemoveXxx 对我来说更有意义。

问题是怎么做呢?

如果我将实体的集合作为 IEnumerables 我无法添加/删除元素到它们而不通过执行 ToList() 将它们转换为列表,这会创建一个新列表,因此无法保留任何内容,或者将它们转换为列表由于代理和延迟加载,这很痛苦。

总体思路是不允许检索实体并直接操作其集合(add.remove 元素),而只能通过我公开的方法,同时尊重集合持久性的级联。

我们将不胜感激您的建议和想法。

【问题讨论】:

    标签: c# nhibernate oop collections


    【解决方案1】:

    怎么样...

    private IList<string> _mappedProperty;
    
    public IEnumerable<string> ExposedProperty
    {
        get { return _mappedProperty.AsEnumerable<string>(); }
    }
    
    public void Add(string value)
    {
        // Apply business rules, raise events, queue message, etc.
        _mappedProperty.Add(value);
    }
    

    如果您使用 NHibernate 映射到私有字段,则此解决方案是可能的,即。 _mapped 属性。您可以在访问和命名策略文档here 中阅读有关如何执行此操作的更多信息。

    事实上,我更喜欢像这样映射我的所有类。最好由开发人员决定如何定义类的公共接口,而不是 ORM。

    【讨论】:

    • 你不需要 AsEnumerable,IList 已经实现了 IEnumerable
    • 这很有意义。我知道并建议其他人将私有属性映射到 NHinernate,但从未设法为这种情况建立连接。谢谢。
    【解决方案2】:

    将它们公开为 ReadOnlyCollection 怎么样?

    IList<SomeObjType> _mappedProperty;
    
    return new ReadOnlyCollection<SomeObjType> ExposedProperty
    {
      get
      {
        return new ReadOnlyCollection(_mappedProperty);
      }
    }
    

    【讨论】:

    • ReadOnlyCollection 是我想到的一个选项,它可以在非 NHibernate 上下文中很好地工作。在将它与 NHibernate 一起使用时,我遇到了映射问题,因为它需要映射到一个单独的私有字段,该字段在构造 ReadOnlyCollection 属性时必须初始化,我正在寻找一种模式实践形式的替代方案。不过感谢您的回答!
    【解决方案3】:

    我正在使用 NHibernate,我通常将集合保存为 ISet 并使 setter 受到保护。

    ISet<SomeObjType> MyProperty { get; protected set; }
    

    我还为需要的集合属性提供了 AddXxx 和 RemoveXxx。这对我来说大部分时间都非常令人满意。但我要说的是,在某些情况下,允许客户端代码直接将项目添加到集合中是有意义的。

    基本上,我所看到的是,如果我在我的客户端代码中遵循"Tell, Don't Ask" 的原则,而不必过多担心对我的域对象属性实施严格的访问限制,那么我总能得到一个好的设计。

    【讨论】:

    • 感谢您的回答 Rohit。正如我在我的问题中提到的那样,我也使 setter 在大多数情况下都受到保护,但这并不允许客户端代码使用集合直接绕过 AddXxx/RemoveXxx 方法中的逻辑来添加/删除元素。受保护的只是防止客户端代码用新的代码完全覆盖整个集合。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-17
    相关资源
    最近更新 更多