C#驱动序列化文档对象

介绍

本文档基于C#官方驱动1.8版本。

本节C#驱动教程谈论C#类到BSON对象的序列化和反序列化。序列化是映射一个对象到可保存到MongoDB库中BSON对象的过程,反序列化由BSON文档重建对象的逆过程。因此,序列化过程通常被称为“对象映射”

序列化使用BSON库处理。BSON库拥有一个可扩展的序列化结构,所以你可以控制你的序列化方式。BSON库提供的默认的序列化其可以满足你大部分的需求,如果你需要特殊处理,你可以对其进行扩展。

默认序列化器通过“类映射”来处理。类映射是定义类和BSON文档对象间映射的一种结构,它包含一系列参与序列化的字段或属性并且为每一个定义了所需的序列化参数(例如,BSON元素名,代表选项等)。

默认的序列化器也内建了对.NET数据类型(原始类型、数组、集合、字典等)的支持。

序列化一个类对象之前,该类映射必须存在,可以手动创建类映射也可以简单的通过自动映射来创建。你可以在类自动映射的过程中通过使用序列化相关特性或者初始化代码的方式施加一些控制。

创建类映射

在你的初始化代码中创建类映射:

BsonClassMap.RegisterClassMap<MyClass>();

在此MyClass 会被自动映射或者注册,当然你可以让你的类通过序列化器自动映射。

如果你想控制创建的类映射,你可以在一个lambda表达式中提供您自己的初始化代码:

BsonClassMap.RegisterClassMap<MyClass)(cm => {

    cm.MapProperty(c => c.SomeProperty);

    cm.MapProperty(c => c.AnotherProperty);

});

当lambda表达式执行“CM”(简称类映射),参数传递一个空类映射供您填充。在本例子中两个属性通过调用MapProperty 方法被添加进去,传进MapProperty 的参数是它们本身。使用lambda表达式,而不是仅仅使用一个字符串参数的属性名称的优点是IntelliSense和编译时检查,确保你正确的拼写属性名称。

另外,也可以使用自动映射,然后覆写一些结果。稍后我们将会看到这方面的例子。

注意类映射必须只能被注册一次(如果你试着多次注册同一个类,会抛出异常)。

通常情况,你可以在只执行一次的代码路径中调用RegisterClassMap (Main 方法,Application_Start 事件等),如果你在执行次数多于一次的代码路径中调用RegisterClassMap 方法,你也可以通过调用IsClassMapRegistered 来检查该类是否被注册过:

if (!BsonClassMap.IsClassMapRegistered(typeof(MyClass))) {

   // 为MyClass注册类映射

}

Creator Maps

默认情况下,类必定包括一个无参的构造函数来用于类的实例化,然后配置一个具有和映射属性相关的参数的构造函数是可以的,有两种方法可以实现:

使用一个表达式,你可以按照下面方式通过驱动使用一个creator map

public class Person

{

  public string FirstName { get; private set; }

  public string LastName { get; private set; }

  public Person(string firstName, string lastName)

  {

    FirstName = firstName;

    LastName = lastName;

  }

}

BsonClassMap.RegisterClassMap<Person>(cm =>

{

    cm.AutoMap();

    cm.MapCreator(p => new Person(p.FirstName, p.LastName));

});

解析表达式树使构造函数第一个参数和FirstName 相关,使构造函数第二个参数和LastName 属性相关。还有其他更复杂的方式处理这种情况,当需要时,可以研究探索。

通过特性:

public class Person

{

  public string FirstName { get; set; }

  public string LastName { get; set; }

  [BsonConstructor]

  public Person(string firstName, string lastName)

  {

    FirstName = firstName;

    LastName = lastName;

  }

}

当不止一个构造函数是,我们通过“满足大多数参数”这一策略来确定哪个是最好的匹配,例如:

public class Person

{

  public string FirstName { get; set; }

  public string LastName { get; set; }

  public DateTime? BirthDate { get; set; }

  [BsonConstructor]

  public Person(string firstName, string lastName)

  {

    // snip...

  }

  [BsonConstructor]

  public Person(string firstName, string lastName, DateTime birthDate)

  {

    // snip...

  }

}

如果数据库中文档对象有一个BirthDate字段,我们会选择使用包含3个参数的构造函数,因为它更具体。

除了上面代码和属性的形式,映射一创建者可以通过约定(约束)来处理。

约定(约束)

自动进行类映射有许多需要考虑的方面,例如

. 例如

  • 哪个字段或属性应该被序列化
  • 哪个字段或属性是ID列
  • 什么元素名称可以被用在BSON文档中
  • 如果是多态,怎么确定使用哪个
  • 如果我们无法识别一个BSON文档中包含的元素会如何
  • 字段或属性是否有一个默认值
  • 默认值应该被序列化还是被忽略
  • null 值应该被序列化还是被忽略

这些问题的答案就代表一组约定。对于每一个约定都有一个默认的惯例,它是最有可能被您使用的一个,在必要时也可以重新个别约定(甚至写你自己的)。

如果你想使用和默认约定不同的自己的约定,可以很简单的创建一个ConventionPack 的实例,添加你想使用的约定进去,然后注册(换句话说,当你使用具体约定的时候通知序列化器)。例如:

var myConventions = new ConventionPack();

pack.Add(new CamelCaseElementNameConvention());

ConventionRegistry.Register(

   "My Custom Conventions",

   pack,

   t => t.FullName.StartsWith("MyNamespace."));

第三个参数是用来定义何时使用这个约定包的过滤器方法。在这种情况下,也就是指如果任何类的全名以MyNamespace开头的话应该使用myConventions约定。

由上面我们已经了解到,除了预定的约定(约束),你可以自定义自己的约定(约束)。有4个可以让我们创建和注册自定义约定的类,运行在不同(阶段)级别。

  1. 类(阶段)级别IClassMapConvention

运行针对类映射阶段.

  1. 方法(成员) 级别(阶段)IMemberMapConvention

运行针对在IClassMapConvention 阶段发现映射的每名成员

  1. Creator 阶段ICreatorMapConvention

运行针对在IClassMapConvention 阶段发现映射的CreatorMap

  1. 后期处理阶段: IPostProcessingConvention

运行针对类映射阶段.

约定在他们注册的每个阶段顺序运行,默认的约定会先注册,这就允许任何用户注册的约定覆盖掉默认的约定。所以某些值可能得到应用和覆写,这就要求用户确保注册顺序的正确性。

注意:

如果一个IPostProcessingConvention 的自定义实现的注册早于一个IClassMapConvention的自定义实现,那么IClassMapConvention 先运行,因为它是运行类阶段是早于后处理阶段的。

待续。。。。

下篇介绍:

Field or Property Level Serialization Options

MongoDB学习(翻译5)的更多相关文章

  1. MongoDB学习3

    MongoDB学习(翻译3)   支持的where字句(比较多,今天先写一部分) 本节介绍支持的where字句 正如前面提到的,不是所有的C#表达式都支持where子句.您可以以此文为指导,或者你可以 ...

  2. MongoDB学习2

    MongoDB学习(翻译2) C#驱动之LINQ教程 介绍 本教程涵盖了1.8发布版本对linq查询的支持. 开始本教程之前,你应该至少阅读下C#驱动教程关于C#驱动的介绍 快速开始 首先,添加下面命 ...

  3. MongoDB学习笔记二- Mongoose

    MongoDB学习笔记二 Mongoose Mongoose 简介 之前我们都是通过shell来完成对数据库的各种操作, 在开发中大部分时候我们都需要通过程序来完成对数据库的操作 而Mongoose就 ...

  4. MongoDB学习笔记系列

    回到占占推荐博客索引 该来的总会来的,Ef,Redis,MVC甚至Sqlserver都有了自己的系列,MongoDB没有理由不去整理一下,这个系列都是平时在项目开发时总结出来的,希望可以为各位一些帮助 ...

  5. MongoDB学习笔记—Linux下搭建MongoDB环境

    1.MongoDB简单说明 a MongoDB是由C++语言编写的一个基于分布式文件存储的开源数据库系统,它的目的在于为WEB应用提供可扩展的高性能数据存储解决方案. b MongoDB是一个介于关系 ...

  6. Mongodb学习笔记一(Mongodb环境配置)

    Mongodb学习 说明: MongoDB由databases组成,database由collections组成,collection由documents组成,document由fileds组成.Mo ...

  7. MongoDB学习记录

    一.操作符 "$lt" :"<""$lte" :"<=""$gt" :"> ...

  8. PHP操作MongoDB学习笔记

    <?php/*** PHP操作MongoDB学习笔记*///*************************//**   连接MongoDB数据库  **////*************** ...

  9. MongoDB学习:(二)MongoDB简单使用

    MongoDB学习:(二)MongoDB简单使用 MongoDB使用: 执行mongodb的操作之前,我们需要运行命令,来进入操作命令界面 >mongo 提示该错误,说明我们系统缺少一个补丁,该 ...

  10. MongoDB学习:(一)MongoDB安装

    MongoDB学习:(一)MongoDB安装 MongoDB介绍:     直接百科了: MongoDB安装: 1:下载安装: MongoDB安装:https://www.mongodb.com/do ...

随机推荐

  1. 使用Json让Java和C#沟通的方法

    原文:使用Json让Java和C#沟通的方法 最近很忙啊,新项目下来了,都没时间写博客了.频率降低点,但不能不总结跟大家分享啊. 我们在项目里经常要涉及到各模块间的通信,这其中又不可避免要碰到各类语言 ...

  2. Swift语言指南(三)--语言基础之整数和浮点数

    原文:Swift语言指南(三)--语言基础之整数和浮点数 整数 整数指没有小数的整数,如42,-23.整数可以是有符号的(正数,零,负数),也可以是无符号的(正数,零). Swift提供了8,16,3 ...

  3. 搭建一个三台服务器的Memcached集群

    关于memcached的基础知识可以查看博客其他博文,这里只记录了搭建的过程,谢谢! 1.分别在三台服务器上安装Memcached并启动 第一.由于memcached是基于libevent的事件处理, ...

  4. HTTP 错误500.19 -Internal Server Error

    原文:HTTP 错误500.19 -Internal Server Error HTTP 错误500.19 -Internal Server Error 错误代码 0x80070021 评论1 字号: ...

  5. Java判断当前用户数及当前登录用户数工具类-session原理

    JavaWeb开发中,有时会遇到统计或管理用户登录数或者当前在线多少用户,分别都是谁的情况.当然,实现途径多种多样.下面列举一下通过session实现的一种统计. public class MySes ...

  6. asp.net读取CSV

    原文:asp.net读取CSV 用Excel导了两天数据,各种问题,折磨客户也折磨了自己,以前没发现的问题一下子都暴露出来了 特意收集两篇Excel跟CSV读取相关的两篇文章 asp.net读取exc ...

  7. javascript 控制台输出 图片 console.log 真强大 真佩服你们的创造力

    无意中,在百度知道页面发现了这货.居然能输出图片到控制台. 完全颠覆自己的三观,果断查阅其输出方法.后得知,原来如此. 曾经做过的项目中,同事把控制台做成一个网页形式方便远程控制和远程调用.没想到过这 ...

  8. yii性能调节

    网络应用程序的性能受很多因素的影响.数据库存取,文件系统操作,网络带宽等都是潜在的影响因素. Yii 已在各个方面减少框架带来的性能影响.但是在用户的应用中仍有很多地方可以被改善来提高性能. 1. 开 ...

  9. DDD,ORM还是Ado.Net

    三层还是DDD,ORM还是Ado.Net,何去何从? 我本想把这个问题放到博问去,前几次有去博问问过之类的问题,无奈大神们可能都不屑回答别人的低级问题.所以放到随笔里,一方面把自己对ORM.架构的一些 ...

  10. 转载:Linux Used内存到底到哪里去了?

    转自:http://blogread.cn/it/article/6264?f=wb2 有时在Linux下会碰到这样的问题:ps aux看到的RSS内存只有不到30M,但是free看到内存却已经使用了 ...