/// <summary> /// Converts BSON to CLR value 1:1, without type change /// </summary> protected virtual object DirectConvertBSONValue(BSONElement element, Func <BSONDocument, BSONElement, bool> filter = null) { if (element == null || element is BSONNullElement) { return(null); } if (element.ElementType == BSONElementType.Document) { return(BSONDocumentToJSONMap(((BSONDocumentElement)element).Value, filter)); } if (element.ElementType == BSONElementType.Array) { var bsonArr = (BSONArrayElement)element; var lst = new List <object>(); foreach (var elm in bsonArr.Value) { lst.Add(DirectConvertBSONValue(elm, filter)); } return(lst.ToArray()); } switch (element.ElementType) { case BSONElementType.ObjectID: return(((BSONObjectIDElement)element).Value.AsGDID); case BSONElementType.Binary: return(((BSONBinaryElement)element).Value.Data); } return(element.ObjectValue); }
protected override void ReadValueFromStream(Stream stream) { var elements = new List <BSONElement>(); long start = stream.Position; var totalSize = BinUtils.ReadInt32(stream); long read = 4; while (read < totalSize - 1) { var et = BinUtils.ReadElementType(stream); var factory = BSONElement.GetElementFactory(et); var element = factory(stream);//element made element.MarkAsArrayItem(); elements.Add(element); read = stream.Position - start; } Value = elements.ToArray(); var terminator = BinUtils.ReadByte(stream); if (terminator != BinUtils.TERMINATOR || stream.Position - start != totalSize) { throw new BSONException(StringConsts.BSON_EOD_ERROR); } }
public TemplateArg(BSONElement element) { if (element == null || element.IsArrayElement) { throw new BSONException(StringConsts.ARGUMENT_ERROR + "TemplateArg.ctor(element==null|IsArrayElement)"); } Name = element.Name; BSONType = element.ElementType; Value = element.ObjectValue; }
protected virtual bool SetAmorphousFieldAsCLR(IAmorphousData amorph, BSONElement bsonElement, string targetName, Func <BSONDocument, BSONElement, bool> filter) { object clrValue; if (!TryConvertBSONtoCLR(typeof(object), bsonElement, targetName, out clrValue, filter)) { return(false); } amorph.AmorphousData[bsonElement.Name] = clrValue; return(true); }
//public static Amount Amount_BSONtoCLR(BSONDocument bson) //{ // var iso = bson.GetValue("c", string.Empty).ToString(); // var value = Decimal_BSONtoCLR(bson.GetValue("v", 0L).ToString()); // return new Amount(iso, value); //} protected virtual bool TrySetFieldAsCLR(Row row, Schema.FieldDef field, BSONElement value, string targetName, Func <BSONDocument, BSONElement, bool> filter) { object clrValue; if (!TryConvertBSONtoCLR(field.NonNullableType, value, targetName, out clrValue, filter)) { return(false); } row.SetFieldValue(field, clrValue); return(true); }
public static decimal Decimal_BSONtoCLR(BSONElement el) { if (el is BSONInt32Element) { return(Decimal_BSONtoCLR((BSONInt32Element)el)); } if (el is BSONInt64Element) { return(Decimal_BSONtoCLR((BSONInt64Element)el)); } throw new BSONException(StringConsts.BSON_DECIMAL_INT32_INT64_CONVERTION_ERROR); }
/// <summary> /// Converts BSON to CLR value 1:1, without type change /// </summary> protected virtual object DirectConvertBSONValue(BSONElement element, Func<BSONDocument, BSONElement, bool> filter = null) { if (element==null) return null; if (element.ElementType == BSONElementType.Document) return BSONDocumentToJSONMap(((BSONDocumentElement)element).Value, filter); if (element.ElementType == BSONElementType.Array) { var bsonArr = (BSONArrayElement)element; var lst = new List<object>(); foreach(var elm in bsonArr.Value) lst.Add( DirectConvertBSONValue(elm, filter) ); return lst.ToArray(); } switch (element.ElementType) { case BSONElementType.ObjectID: return ((BSONObjectIDElement)element).Value.AsGDID; case BSONElementType.Binary: return ((BSONBinaryElement)element).Value.Data; } return element.ObjectValue; }
/// <summary> /// Tries to convert the BSON value into target CLR type. Returns true if conversion was successfull /// </summary> protected virtual bool TryConvertBSONtoCLR(Type target, BSONElement element, string targetName, out object clrValue, Func<BSONDocument, BSONElement, bool> filter) { if (element==null) { clrValue = null; return true; } if (target == typeof(object)) { //just unwrap Bson:CLR = 1:1, without type conversion clrValue = DirectConvertBSONValue( element, filter ); return true; } clrValue = null; if (target.IsSubclassOf(typeof(TypedRow))) { var bsonDocumentElement = element as BSONDocumentElement; var doc = bsonDocumentElement != null ? bsonDocumentElement.Value : null; if (doc==null) return false;//not document var tr = (TypedRow)Activator.CreateInstance(target); BSONDocumentToRow(doc, tr, targetName, filter: filter); clrValue = tr; return true; } //ARRAY if (target.IsArray && target.GetArrayRank()==1 && target!=typeof(byte[]))//exclude byte[] as it is treated with m_BSONtoCLR { var bsonArrayElement = element as BSONArrayElement; var arr = bsonArrayElement != null ? bsonArrayElement.Value : null; if (arr==null) return false;//not array var telm = target.GetElementType(); var clrArray = Array.CreateInstance(telm, arr.Length); for(var i=0; i<arr.Length; i++) { object clrElement; if (!TryConvertBSONtoCLR(telm, arr[i], targetName, out clrElement, filter)) { return false;//could not convert some element of array } clrArray.SetValue(clrElement, i); } clrValue = clrArray; return true; } //LIST<T> if (target.IsGenericType && target.GetGenericTypeDefinition() == typeof(List<>)) { var bsonArrayElement = element as BSONArrayElement; var arr = bsonArrayElement != null ? bsonArrayElement.Value : null; if (arr==null) return false;//not array var gargs = target.GetGenericArguments(); var telm = gargs[0]; var clrList = Activator.CreateInstance(target) as System.Collections.IList; for(var i=0; i<arr.Length; i++) { object clrElement; if (!TryConvertBSONtoCLR(telm, arr[i], targetName, out clrElement, filter)) { return false;//could not convert some element of array into element of List<t> } clrList.Add( clrElement ); } clrValue = clrList; return true; } //JSONDataMap if (target==typeof(JSONDataMap)) { var bsonDocumentElement = element as BSONDocumentElement; var doc = bsonDocumentElement != null ? bsonDocumentElement.Value : null; clrValue = BSONDocumentToJSONMap(doc, filter); return true; } if (target.IsEnum) { try { clrValue = Enum.Parse(target, ((BSONStringElement)element).Value, true); return true; } catch { return false; } } //Primitive type-targeted value Func<BSONElement, object> func; if (m_BSONtoCLR.TryGetValue(target, out func)) { try { clrValue = func(element); } catch { return false;//functor could not convert } return true; } return false;//could not convert }
protected virtual bool SetAmorphousFieldAsCLR(IAmorphousData amorph, BSONElement bsonElement, string targetName, Func<BSONDocument, BSONElement, bool> filter) { object clrValue; if (!TryConvertBSONtoCLR(typeof(object), bsonElement, targetName, out clrValue, filter)) return false; amorph.AmorphousData[bsonElement.Name] = clrValue; return true; }
//public static Amount Amount_BSONtoCLR(BSONDocument bson) //{ // var iso = bson.GetValue("c", string.Empty).ToString(); // var value = Decimal_BSONtoCLR(bson.GetValue("v", 0L).ToString()); // return new Amount(iso, value); //} protected virtual bool TrySetFieldAsCLR(Row row, Schema.FieldDef field, BSONElement value, string targetName, Func<BSONDocument, BSONElement, bool> filter) { object clrValue; if (!TryConvertBSONtoCLR(field.NonNullableType, value, targetName, out clrValue, filter)) return false; row.SetFieldValue(field, clrValue); return true; }
/// <summary> /// Tries to convert the BSON value into target CLR type. Returns true if conversion was successfull /// </summary> protected virtual bool TryConvertBSONtoCLR(Type target, BSONElement element, string targetName, out object clrValue, Func <BSONDocument, BSONElement, bool> filter) { if (element == null || element is BSONNullElement) { clrValue = null; return(true); } if (target == typeof(object)) { //just unwrap Bson:CLR = 1:1, without type conversion clrValue = DirectConvertBSONValue(element, filter); return(true); } clrValue = null; if (target.IsSubclassOf(typeof(TypedRow))) { var bsonDocumentElement = element as BSONDocumentElement; var doc = bsonDocumentElement != null ? bsonDocumentElement.Value : null; if (doc == null) { return(false); //not document } var tr = (TypedRow)Activator.CreateInstance(target); BSONDocumentToRow(doc, tr, targetName, filter: filter); clrValue = tr; return(true); } //ARRAY if (target.IsArray && target.GetArrayRank() == 1 && target != typeof(byte[]))//exclude byte[] as it is treated with m_BSONtoCLR { var bsonArrayElement = element as BSONArrayElement; var arr = bsonArrayElement != null ? bsonArrayElement.Value : null; if (arr == null) { return(false); //not array } var telm = target.GetElementType(); var clrArray = Array.CreateInstance(telm, arr.Length); for (var i = 0; i < arr.Length; i++) { object clrElement; if (!TryConvertBSONtoCLR(telm, arr[i], targetName, out clrElement, filter)) { return(false);//could not convert some element of array } clrArray.SetValue(clrElement, i); } clrValue = clrArray; return(true); } //LIST<T> if (target.IsGenericType && target.GetGenericTypeDefinition() == typeof(List <>)) { var bsonArrayElement = element as BSONArrayElement; var arr = bsonArrayElement != null ? bsonArrayElement.Value : null; if (arr == null) { return(false); //not array } var gargs = target.GetGenericArguments(); var telm = gargs[0]; var clrList = Activator.CreateInstance(target) as System.Collections.IList; for (var i = 0; i < arr.Length; i++) { object clrElement; if (!TryConvertBSONtoCLR(telm, arr[i], targetName, out clrElement, filter)) { return(false);//could not convert some element of array into element of List<t> } clrList.Add(clrElement); } clrValue = clrList; return(true); } //JSONDataMap if (target == typeof(JSONDataMap)) { var bsonDocumentElement = element as BSONDocumentElement; var doc = bsonDocumentElement != null ? bsonDocumentElement.Value : null; clrValue = BSONDocumentToJSONMap(doc, filter); return(true); } if (target.IsEnum) { try { clrValue = Enum.Parse(target, ((BSONStringElement)element).Value, true); return(true); } catch { return(false); } } //Primitive type-targeted value Func <BSONElement, object> func; if (m_BSONtoCLR.TryGetValue(target, out func)) { try { clrValue = func(element); } catch (Exception error) { Debug.Fail("Error in BSONRowConverter.TryConvertBSONtoCLR(): " + error.ToMessageWithType()); return(false);//functor could not convert } return(true); } return(false);//could not convert }
public void WriteStringInt32DoubleMixedArray() { using (var stream = new MemoryStream()) using (var reader = new BinaryReader(stream)) { var root = new BSONDocument(); var array = new BSONElement[] { new BSONStringElement("apple"), new BSONInt32Element(3), new BSONDoubleElement(2.14D) }; root.Set(new BSONArrayElement("stuff", array)); root.WriteAsBSON(stream); Assert.AreEqual(stream.Position, 48); // ensure document length is 48 bytes stream.Seek(0, SeekOrigin.Begin); CollectionAssert.AreEqual(reader.ReadBytes(4), BitConverter.GetBytes(48)); // document's content length is 48 Assert.AreEqual(reader.ReadByte(), (byte)BSONElementType.Array); // element type is array 0x04 CollectionAssert.AreEqual(reader.ReadBytes(5), Encoding.UTF8.GetBytes("stuff")); // element name is 'stuff' Assert.AreEqual(reader.ReadByte(), (byte)0x00); // string name terminator 0x00 is present CollectionAssert.AreEqual(reader.ReadBytes(4), BitConverter.GetBytes(36)); // array's content length is 36 Assert.AreEqual(reader.ReadByte(), (byte)BSONElementType.String); // element type is string 0x02 CollectionAssert.AreEqual(reader.ReadBytes(1), Encoding.UTF8.GetBytes("0")); // element name is '0' Assert.AreEqual(reader.ReadByte(), (byte)0x00); // last byte is terminator 0x00 CollectionAssert.AreEqual(reader.ReadBytes(4), BitConverter.GetBytes(6)); // string content length is 6 CollectionAssert.AreEqual(reader.ReadBytes(5),Encoding.UTF8.GetBytes("apple")); // string content length is 'apple' Assert.AreEqual(reader.ReadByte(), (byte)0x00); // last byte is terminator 0x00 Assert.AreEqual(reader.ReadByte(), (byte)BSONElementType.Int32); // element type is int32 0x10 CollectionAssert.AreEqual(reader.ReadBytes(1), Encoding.UTF8.GetBytes("1")); // element name is '1' Assert.AreEqual(reader.ReadByte(), (byte)0x00); // last byte is terminator 0x00 CollectionAssert.AreEqual(reader.ReadBytes(4), BitConverter.GetBytes(3)); // value is 3 Assert.AreEqual(reader.ReadByte(), (byte)BSONElementType.Double); // element type is double 0x01 CollectionAssert.AreEqual(reader.ReadBytes(1), Encoding.UTF8.GetBytes("2")); // element name is '2' Assert.AreEqual(reader.ReadByte(), (byte)0x00); // last byte is terminator 0x00 CollectionAssert.AreEqual(reader.ReadBytes(8), BitConverter.GetBytes(2.14D)); // value is 2.14 Assert.AreEqual(reader.ReadByte(), (byte)0x00); // ensure last byte is terminator 0x00 Assert.AreEqual(reader.ReadByte(), (byte)0x00); // ensure last byte is terminator 0x00 Assert.AreEqual(stream.Position, 48); // ensure whole document readed } }
/// <summary> /// Array of strings /// { 'stuff': ['apple, 3, 2.14] } --> { 'stuff': { '0': 'apple', '1': 3, '2': 2.14 } } /// </summary> public void WriteStringInt32DoubleMixedArray(Stream stream) { var root = new BSONDocument(); var array = new BSONElement[] { new BSONStringElement("apple"), new BSONInt32Element(3), new BSONDoubleElement(2.14D) }; root.Set(new BSONArrayElement("stuff", array)); root.WriteAsBSON(stream); }