【问题标题】:Deserializing IEnumerable with private backing field in RavenDb在 RavenDb 中使用私有支持字段反序列化 IEnumerable
【发布时间】:2013-03-11 08:49:31
【问题描述】:

我已经为域建模了几天,根本没有考虑持久性,而是专注于域逻辑。现在我准备好持久化我的域对象,其中一些包含 IEnumerable 的子实体。使用 RavenDb,持久性很“容易”,但是当再次加载我的对象时,所有 IEnumerables 都是空的。

我意识到这是因为他们根本没有任何属性设置器,而是使用列表作为支持字段。域聚合根的用户可以通过公共方法而不是直接在集合上添加子实体。

private readonly List<VeryImportantPart> _veryImportantParts;
public IEnumerable<VeryImportantPart> VeryImportantParts { get { return _veryImportantParts; } }

还有添加的方法,没什么花哨的……

public void AddVeryImportantPart(VeryImportantPart part)
{
    // some logic...
    _veryImportantParts.Add(part);
}

我可以通过在所有带有支持字段的 IEnumerables 上添加一个私有/受保护的设置器来解决此问题,但它看起来......嗯......不是超级性感。

private List<VeryImportantPart> _veryImportantParts;
public IEnumerable<VeryImportantPart> VeryImportantParts
{
    get { return _veryImportantParts; }
    protected set { _veryImportantParts = value.ToList(); }
}

现在 RavenDb json 序列化程序将在加载时再次填充我的对象,但我很好奇是否有更简洁的方法来执行此操作?

我一直在摆弄 JsonContractResolver 但还没有找到解决方案...

【问题讨论】:

    标签: ravendb


    【解决方案1】:

    我想我已经找到了这个问题的根本原因,这可能是因为我的许多实体是使用以下方法创建的:

    protected MyClass(Guid id, string name, string description) : this()
    { .... }
    
    public static MyClass Create(string name, string description)
    {
        return new MyClass(Guid.NewGuid(), name, description);
    }
    

    反序列化时,RavenDb/Json.net 无法以正确的方式重建我的实体...

    改用公共构造函数就大不一样了。

    【讨论】:

    • 您也可以尝试添加私有或受保护的无参数构造函数。
    【解决方案2】:

    需要保留一个私有的支持字段吗?通常一个自动属性就可以了。

    public IList<VeryImportantPart> VeryImportantParts { get; protected set; }
    

    这样做时,您可能希望在构造函数中初始化列表:

    VeryImportantParts = new List<VeryImportantPart>();
    

    当然,这是可选的,但它允许您在持久化之前创建一个新类并立即开始添加到列表中。当 Raven 反序列化一个类时,它会使用 setter 覆盖默认的空白列表,所以这对第一次存储有帮助。

    您当然不能使用readonly 字段,因为在反序列化期间无法替换它。 也许可以编写一个合同解析器或转换器来填充现有列表而不是创建一个新列表,但这似乎是一个相当复杂的解决方案。

    无论如何,使用自动属性可以使您的代码更加清晰 - 因为使用字段或属性更容易混淆。

    【讨论】:

    • 好吧,我真的不想将 IList 公开给该域对象的“用户”以随心所欲地做,而是使用更能揭示意图的界面,正如 Jimmy Bogard 在这里描述的那样@ 987654321@
    • 是的,有时可能需要。不幸的是,很难以一种形式显示,而以另一种形式反序列化。您如何描述添加受保护或私有设置器是一种解决方案。另一种方法是拥有一个自动私有属性并使用诸如public IEnumerable GetVeryImportantParts()之类的方法进行显示
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-17
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    相关资源
    最近更新 更多