【问题标题】:Default MongoDB serialization of public properties公共属性的默认 MongoDB 序列化
【发布时间】:2012-08-29 02:28:34
【问题描述】:

我了解我的类必须具有公共读写属性,以便 MongoDB 驱动程序序列化/反序列化我的对象。但是我想知道是否有方法/首选方法可以从我的其余代码中隐藏写入属性?

例如。

class Product
{
    private List<Release> releases;

    public List<Release> Releases
    {
        get
        {
            return new List<Release>(releases); //I can protect 'releases' when reading by passing a copy of it
        }
        set
        {
            releases = value; //BUT how can I protect release when writing?
        }
    }
}

我希望 MongoDB 能够序列化/反序列化我的类型,但我不希望我的其余代码能够覆盖原本应该是私有的字段/属性。有没有一种模式来处理这个?我曾想过有一个单独的 ProductDoc 类,它只是用作将 Product 对象进出 MongoDB 的中介,但我不确定是否有更好的解决方案。

【问题讨论】:

    标签: c# mongodb serialization


    【解决方案1】:

    我已经很长时间没有使用 mongo 了。但是您可以尝试阅读此线程 MongoDb Map Setters 或尝试像这样保护您的 setter:

    public List<Release> Releases
    {
        get
        {
            return new List<Release>(releases); //I can protect 'releases' when reading by passing a copy of it
        }
        protected set
        {
            releases = value; //BUT how can I protect release when writing?
        }
    }
    

    【讨论】:

    • 即使使用受保护和私有的 setter mongo 驱动程序也能够序列化和反序列化我的类?我只是问,因为 mongo 文档说要可序列化,它必须具有公共 getter 和 setter 属性以及无参数公共构造函数。
    • 它有效。测试应用程序始终是证明 api 的好方法。
    • 这个解决方案有点工作,但它也引入了一个潜在的无法检测到的构建问题。确实,通过使 SET 私有或受保护,MongoDB 仍然可以序列化和反序列化对象,并且如果您尝试设置属性的值,但如果您执行类似 .Add(new Release{}) 之类的操作,则无法构建只会构建您的项目,但您将修改集合。
    【解决方案2】:

    如果您的属性是由构造函数设置的,另一种方法是将它们保持为只读,并使用MapCreator 告诉 MongoDB 如何创建您的类的实例,并传入您要设置的属性。

    例如我有一个名为 Time 的类,它具有三个只读属性:Hour、Minute 和 Second,以及一个需要一小时、一分钟和第二个值的公共构造函数。

    这是我如何让 MongoDB 将这三个值存储在数据库中并在反序列化期间构造新的 Time 对象。

    BsonClassMap.RegisterClassMap<Time>(cm =>
    {
        cm.AutoMap();
        cm.MapCreator(p => new Time(p.Hour, p.Minute, p.Second));
        cm.MapProperty(p => p.Hour);
        cm.MapProperty(p => p.Minute);
        cm.MapProperty(p => p.Second);
    }
    

    【讨论】:

      【解决方案3】:

      此页面上的最佳答案目前存在一些重要的缺陷。

      正如目前所写的解决方案:

      public List<Release> Releases
      {
          get
          {
              return new List<Release>(releases); //I can protect 'releases' when reading by passing a copy of it
          }
          protected set
          {
              releases = value; //BUT how can I protect release when writing?
          }
      }
      

      这不像写的那样工作。

      obj.Releases.Add(new Release());
      

      会通过向其添加新版本来影响基础集合。这与将 set 例程设为私有的既定目标直接矛盾。

      但是,如果您更改公开的属性类型以实现 IEnumerable 而不是 List 并返回列表的只读版本。比如……

      public IEnumerable<Release> Releases
      {
          get
          {
              return new List<Release>(releases).AsReadOnly();
          }
          protected set
          {
              releases = value;
          }
      }
      

      然后两个

      obj.Releases.Add(new Release());
      

      和

      obj.Releases = new List<Release>();
      

      将引发构建错误并阻止修改基础集合。

      【讨论】:

        猜你喜欢
        • 2011-02-26
        • 1970-01-01
        • 1970-01-01
        • 2015-12-06
        • 2018-11-02
        • 2018-03-06
        • 2020-09-15
        • 2018-08-03
        • 2011-03-25
        相关资源
        最近更新 更多