static BsonDocument ToBsonDocument(BsonDocument source, object value, DocumentInput input, IEnumerable <Selector> properties, int depth) { IncSerializationDepth(ref depth); PSObject custom; value = BaseObject(value, out custom); //_131013_155413 reuse existing document or wrap var cd = value as IConvertibleToBsonDocument; if (cd != null) { // reuse if (source == null && properties == null) { return(cd.ToBsonDocument()); } // wrap return(ToBsonDocumentFromDictionary(source, new Dictionary(cd), input, properties, depth)); } var dictionary = value as IDictionary; if (dictionary != null) { return(ToBsonDocumentFromDictionary(source, dictionary, input, properties, depth)); } return(ToBsonDocumentFromProperties(source, custom ?? new PSObject(value), input, properties, depth)); }
//! For external use only. public static BsonDocument ToBsonDocument(BsonDocument source, object value, DocumentInput input, IEnumerable <Selector> properties) { return(ToBsonDocument(source, value, input, properties, 0)); }
//! IConvertibleToBsonDocument (e.g. Mdbc.Dictionary) must be converted before if source and properties are null static BsonDocument ToBsonDocumentFromDictionary(BsonDocument source, IDictionary dictionary, DocumentInput input, IEnumerable <Selector> properties, int depth) { IncSerializationDepth(ref depth); #if DEBUG if (source == null && properties == null && dictionary is IConvertibleToBsonDocument) { throw new InvalidOperationException("DEBUG: must be converted before."); } #endif // use source or new document var document = source ?? new BsonDocument(); if (properties == null) { foreach (DictionaryEntry de in dictionary) { var name = de.Key as string; if (name == null) { throw new InvalidOperationException("Dictionary keys must be strings."); } document.Add(name, ToBsonValue(de.Value, input, depth)); } } else { foreach (var selector in properties) { if (selector.PropertyName != null) { if (dictionary.Contains(selector.PropertyName)) { document.Add(selector.DocumentName, ToBsonValue(dictionary[selector.PropertyName], input, depth)); } } else { document.Add(selector.DocumentName, ToBsonValue(selector.GetValue(dictionary), input, depth)); } } } return(document); }
// Input supposed to be not null static BsonDocument ToBsonDocumentFromProperties(BsonDocument source, PSObject value, DocumentInput input, IEnumerable <Selector> properties, int depth) { IncSerializationDepth(ref depth); var type = value.BaseObject.GetType(); if (type.IsPrimitive || type == typeof(string)) { throw new InvalidCastException(string.Format(null, "Cannot convert {0} to a document.", type)); } // existing or new document var document = source ?? new BsonDocument(); if (properties == null) { foreach (var pi in value.Properties) { try { document.Add(pi.Name, ToBsonValue(pi.Value, input, depth)); } catch (GetValueException) // .Value may throw, e.g. ExitCode in Process { document.Add(pi.Name, BsonNull.Value); } } } else { foreach (var selector in properties) { if (selector.PropertyName != null) { var pi = value.Properties[selector.PropertyName]; if (pi != null) { try { document.Add(selector.DocumentName, ToBsonValue(pi.Value, input, depth)); } catch (GetValueException) // .Value may throw, e.g. ExitCode in Process { document.Add(selector.DocumentName, BsonNull.Value); } } } else { document.Add(selector.DocumentName, ToBsonValue(selector.GetValue(value), input, depth)); } } } return(document); }
static BsonValue ToBsonValue(object value, ScriptBlock convert, int depth) { IncSerializationDepth(ref depth); if (value == null) { return(BsonNull.Value); } value = BaseObject(value, out PSObject custom); // case: custom if (custom != null) { return(ToBsonDocumentFromProperties(null, custom, convert, null, depth)); } // case: BsonValue if (value is BsonValue bson) { return(bson); } // case: string if (value is string text) { return(new BsonString(text)); } // case: document if (value is IConvertibleToBsonDocument cd) { return(cd.ToBsonDocument()); } // case: dictionary if (value is IDictionary dictionary) { return(ToBsonDocumentFromDictionary(null, dictionary, convert, null, depth)); } // case: bytes or collection if (value is IEnumerable en) { //_191108_183844 if (en is byte[] bytes) { return(new BsonBinaryData(bytes)); } var array = new BsonArray(); foreach (var it in en) { array.Add(ToBsonValue(it, convert, depth)); } return(array); } // try to map BsonValue if (BsonTypeMapper.TryMapToBsonValue(value, out BsonValue bson2)) { return(bson2); } // try to serialize class var type = value.GetType(); if (TypeIsDriverSerialized(type)) { return(BsonExtensionMethods.ToBsonDocument(value, type)); } // no converter? die if (convert == null) { //! use this type throw new ArgumentException(Res.CannotConvert2(type, nameof(BsonValue))); } try { value = DocumentInput.ConvertValue(convert, value); } catch (RuntimeException re) { //! use this type throw new ArgumentException($"Converter script was called for '{type}' and failed with '{re.Message}'.", re); } // do not pass converter twice return(ToBsonValue(value, null, depth)); }
static BsonValue ToBsonValue(object value, DocumentInput input, int depth) { IncSerializationDepth(ref depth); if (value == null) { return(BsonNull.Value); } PSObject custom; value = BaseObject(value, out custom); // case: custom if (custom != null) { return(ToBsonDocumentFromProperties(null, custom, input, null, depth)); } // case: BsonValue var bson = value as BsonValue; if (bson != null) { return(bson); } // case: string var text = value as string; if (text != null) { return(new BsonString(text)); } // case: document var cd = value as IConvertibleToBsonDocument; if (cd != null) { return(cd.ToBsonDocument()); } // case: dictionary var dictionary = value as IDictionary; if (dictionary != null) { return(ToBsonDocumentFromDictionary(null, dictionary, input, null, depth)); } // case: collection var enumerable = value as IEnumerable; if (enumerable != null) { var array = new BsonArray(); foreach (var it in enumerable) { array.Add(ToBsonValue(it, input, depth)); } return(array); } // try to create BsonValue try { return(BsonValue.Create(value)); } catch (ArgumentException ae) { if (input == null) { throw; } try { value = input.ConvertValue(value); } catch (RuntimeException re) { throw new ArgumentException( //! use this type string.Format(null, @"Converter script was called on ""{0}"" and failed with ""{1}"".", ae.Message, re.Message), re); } if (value == null) { throw; } // do not call converter twice return(ToBsonValue(value, null, depth)); } }
static BsonValue ToBsonValue(object value, DocumentInput input, int depth) { IncSerializationDepth(ref depth); if (value == null) return BsonNull.Value; PSObject custom; value = BaseObject(value, out custom); // case: custom if (custom != null) return ToBsonDocumentFromProperties(null, custom, input, null, depth); // case: BsonValue var bson = value as BsonValue; if (bson != null) return bson; // case: string var text = value as string; if (text != null) return new BsonString(text); // case: document var cd = value as IConvertibleToBsonDocument; if (cd != null) return cd.ToBsonDocument(); // case: dictionary var dictionary = value as IDictionary; if (dictionary != null) return ToBsonDocumentFromDictionary(null, dictionary, input, null, depth); // case: collection var enumerable = value as IEnumerable; if (enumerable != null) { var array = new BsonArray(); foreach (var it in enumerable) array.Add(ToBsonValue(it, input, depth)); return array; } // try to create BsonValue try { Register(); return BsonValue.Create(value); } catch (ArgumentException ae) { if (input == null) throw; try { value = input.ConvertValue(value); } catch (RuntimeException re) { throw new ArgumentException( //! use this type string.Format(null, @"Converter script was called on ""{0}"" and failed with ""{1}"".", ae.Message, re.Message), re); } if (value == null) throw; // do not call converter twice return ToBsonValue(value, null, depth); } }
// Input supposed to be not null static BsonDocument ToBsonDocumentFromProperties(BsonDocument source, PSObject value, DocumentInput input, IEnumerable<Selector> properties, int depth) { IncSerializationDepth(ref depth); var type = value.BaseObject.GetType(); if (type.IsPrimitive || type == typeof(string)) throw new InvalidCastException(string.Format(null, "Cannot convert {0} to a document.", type)); // existing or new document var document = source ?? new BsonDocument(); if (properties == null) { foreach (var pi in value.Properties) { try { document.Add(pi.Name, ToBsonValue(pi.Value, input, depth)); } catch (GetValueException) // .Value may throw, e.g. ExitCode in Process { document.Add(pi.Name, BsonNull.Value); } } } else { foreach (var selector in properties) { if (selector.PropertyName != null) { var pi = value.Properties[selector.PropertyName]; if (pi != null) { try { document.Add(selector.DocumentName, ToBsonValue(pi.Value, input, depth)); } catch (GetValueException) // .Value may throw, e.g. ExitCode in Process { document.Add(selector.DocumentName, BsonNull.Value); } } } else { document.Add(selector.DocumentName, ToBsonValue(selector.GetValue(value), input, depth)); } } } return document; }
//! IConvertibleToBsonDocument (e.g. Mdbc.Dictionary) must be converted before if source and properties are null static BsonDocument ToBsonDocumentFromDictionary(BsonDocument source, IDictionary dictionary, DocumentInput input, IEnumerable<Selector> properties, int depth) { IncSerializationDepth(ref depth); #if DEBUG if (source == null && properties == null && dictionary is IConvertibleToBsonDocument) throw new InvalidOperationException("DEBUG: must be converted before."); #endif // use source or new document var document = source ?? new BsonDocument(); if (properties == null) { foreach (DictionaryEntry de in dictionary) { var name = de.Key as string; if (name == null) throw new InvalidOperationException("Dictionary keys must be strings."); document.Add(name, ToBsonValue(de.Value, input, depth)); } } else { foreach (var selector in properties) { if (selector.PropertyName != null) { if (dictionary.Contains(selector.PropertyName)) document.Add(selector.DocumentName, ToBsonValue(dictionary[selector.PropertyName], input, depth)); } else { document.Add(selector.DocumentName, ToBsonValue(selector.GetValue(dictionary), input, depth)); } } } return document; }
static BsonDocument ToBsonDocument(BsonDocument source, object value, DocumentInput input, IEnumerable<Selector> properties, int depth) { IncSerializationDepth(ref depth); PSObject custom; value = BaseObject(value, out custom); //_131013_155413 reuse existing document or wrap var cd = value as IConvertibleToBsonDocument; if (cd != null) { // reuse if (source == null && properties == null) return cd.ToBsonDocument(); // wrap return ToBsonDocumentFromDictionary(source, new Dictionary(cd), input, properties, depth); } var dictionary = value as IDictionary; if (dictionary != null) return ToBsonDocumentFromDictionary(source, dictionary, input, properties, depth); return ToBsonDocumentFromProperties(source, custom ?? new PSObject(value), input, properties, depth); }
//! For external use only. public static BsonDocument ToBsonDocument(BsonDocument source, object value, DocumentInput input, IEnumerable<Selector> properties) { return ToBsonDocument(source, value, input, properties, 0); }