< Summary

Class:Azure.Search.Documents.Models.SearchDocument
Assembly:Azure.Search.Documents
File(s):C:\Git\azure-sdk-for-net\sdk\search\Azure.Search.Documents\src\SearchDocument\SearchDocument.Core.cs
C:\Git\azure-sdk-for-net\sdk\search\Azure.Search.Documents\src\SearchDocument\SearchDocument.cs
C:\Git\azure-sdk-for-net\sdk\search\Azure.Search.Documents\src\SearchDocument\SearchDocument.Dictionary.cs
Covered lines:71
Uncovered lines:25
Coverable lines:96
Total lines:459
Line coverage:73.9% (71 of 96)
Covered branches:59
Total branches:64
Branch coverage:92.1% (59 of 64)

Metrics

MethodCyclomatic complexity Line coverage Branch coverage
SetValue(...)-100%100%
GetValue(...)-100%100%
GetValue(...)-33.33%50%
TryGetValue(...)-75%87.5%
ConvertValue(...)-97.22%96.15%
.ctor()-100%100%
.ctor(...)-100%50%
GetBoolean(...)-100%100%
GetBooleanCollection(...)-100%100%
GetInt32(...)-100%100%
GetInt32Collection(...)-100%100%
GetInt64(...)-100%100%
GetInt64Collection(...)-100%100%
GetDouble(...)-100%100%
GetDoubleCollection(...)-100%100%
GetDateTimeOffset(...)-100%100%
GetDateTimeOffsetCollection(...)-100%100%
GetString(...)-100%100%
GetStringCollection(...)-100%100%
GetObject(...)-100%100%
GetObjectCollection(...)-100%100%
ToString()-0%100%
get_Item(...)-100%100%
set_Item(...)-100%100%
TryGetValue(...)-0%100%
get_Keys()-100%100%
System.Collections.Generic.IDictionary<System.String,System.Object>.get_Values()-0%100%
get_Count()-0%100%
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Object>>.get_IsReadOnly()-0%100%
Add(...)-0%100%
ContainsKey(...)-0%100%
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Object>>.Add(...)-0%100%
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Object>>.Contains(...)-0%100%
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Object>>.CopyTo(...)-0%100%
GetEnumerator()-100%100%
System.Collections.IEnumerable.GetEnumerator()-100%100%
Remove(...)-0%100%
System.Collections.Generic.ICollection<System.Collections.Generic.KeyValuePair<System.String,System.Object>>.Remove(...)-0%100%
Clear()-0%100%

File(s)

C:\Git\azure-sdk-for-net\sdk\search\Azure.Search.Documents\src\SearchDocument\SearchDocument.Core.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.Globalization;
 7using Azure.Core;
 8
 9// This logic belongs in DynamicData, but they may not ship at the same time
 10// so we optionally compile a private version of it into SearchDocument.
 11#if EXPERIMENTAL_DYNAMIC
 12namespace Azure.Core
 13{
 14    public partial class DynamicData
 15#else
 16namespace Azure.Search.Documents.Models
 17{
 18    public partial class SearchDocument
 19#endif
 20    {
 21        /// <summary>
 22        /// The document properties.
 23        /// </summary>
 24        private readonly IDictionary<string, object> _values = null;
 25
 26        /// <summary>
 27        /// Set a document property.
 28        /// </summary>
 29        /// <param name="name">The property name.</param>
 30        /// <param name="value">The property value.</param>
 31        private protected void SetValue(string name, object value)
 32        {
 2754833            Argument.AssertNotNullOrEmpty(name, nameof(name));
 2754834            _values[name] = value;
 2754835        }
 36
 37        /// <summary>
 38        /// Get a document property.
 39        /// </summary>
 40        /// <typeparam name="T">The expected type of the property value.</typeparam>
 41        /// <param name="name">The property name.</param>
 42        /// <returns>The value of the property.</returns>
 35143        private protected T GetValue<T>(string name) => (T)GetValue(name, typeof(T));
 44
 45        /// <summary>
 46        /// Get a document property.
 47        /// </summary>
 48        /// <param name="name">The property name.</param>
 49        /// <param name="type">The expected type of the property value.</param>
 50        /// <returns>The value of the property.</returns>
 51        private protected object GetValue(string name, Type type = null)
 52        {
 2714653            if (!TryGetValue(name, type, out object value))
 54            {
 055                KeyNotFoundException exception = new KeyNotFoundException(
 056                    "Could not find a member called '" + name + "' in the document.");
 057                exception.Data["MissingName"] = name;
 058                throw exception;
 59            }
 2712860            return value;
 61        }
 62
 63        /// <summary>
 64        /// Try to get a document property.
 65        /// </summary>
 66        /// <param name="name">The property name.</param>
 67        /// <param name="type">The expected type of the property value.</param>
 68        /// <param name="value">The value of the property if found.</param>
 69        /// <returns>A value indicating whether the property was found.</returns>
 70        private protected bool TryGetValue(string name, Type type, out object value)
 71        {
 2714672            if (string.IsNullOrEmpty(name))
 73            {
 074                value = null;
 075                return false;
 76            }
 77
 2714678            type ??= typeof(object);
 2714679            bool found = _values.TryGetValue(name, out value);
 2714680            if (found && type != typeof(object))
 81            {
 35182                value = ConvertValue(value, type);
 83            }
 2712884            return found;
 85        }
 86
 87        /// <summary>
 88        /// Attempt to convert a value to the desired type.  This is full of
 89        /// Search specific conversions and I'd expect to be able to override
 90        /// a base version of this provided by DynamicData.
 91        /// </summary>
 92        /// <param name="value">The value to convert.</param>
 93        /// <param name="type">The type to convert to.</param>
 94        /// <returns>The converted value.</returns>
 95        private protected static object ConvertValue(object value, Type type)
 96        {
 97            // Short circuit values that are already in the right format
 55698            if (value == null || type == null || type.IsAssignableFrom(value.GetType()))
 99            {
 133100                return value;
 101            }
 102
 103            // Just unwrap Nullable<>s since we've already handled null above
 423104            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
 105            {
 150106                Type elementType = type.GetGenericArguments()[0];
 150107                return ConvertValue(value, elementType);
 108            }
 109
 110            // Arrays deserialize as object[] but we usually want T[]
 273111            if (type.IsArray && type.GetArrayRank() == 1 && value is Array values)
 112            {
 37113                Type elementType = type.GetElementType();
 37114                int length = values.Length;
 37115                Array converted = Array.CreateInstance(elementType, length);
 180116                for (int i = 0; i < length; i++)
 117                {
 55118                    converted.SetValue(
 55119                        ConvertValue(values.GetValue(i), elementType),
 55120                        i);
 121                }
 35122                return converted;
 123            }
 124
 125            // Special case DateTime/DateTimeOffset/and textual doubles that we
 126            // don't convert until a user requests them in a given format
 236127            if (value is string text)
 128            {
 79129                if (type == typeof(DateTime) &&
 79130                    DateTime.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime date))
 131                {
 0132                    return date;
 133                }
 79134                else if (type == typeof(DateTimeOffset) &&
 79135                    DateTimeOffset.TryParse(text, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTimeOffset 
 136                {
 31137                    return dateOffset;
 138                }
 48139                else if (type == typeof(double))
 140                {
 10141                    if (string.Equals(text, Constants.NanValue, StringComparison.Ordinal))
 142                    {
 2143                        return double.NaN;
 144                    }
 8145                    else if (string.Equals(text, Constants.InfValue, StringComparison.Ordinal))
 146                    {
 2147                        return double.PositiveInfinity;
 148                    }
 6149                    else if (string.Equals(text, Constants.NegativeInfValue, StringComparison.Ordinal))
 150                    {
 2151                        return double.NegativeInfinity;
 152                    }
 153                }
 154            }
 155
 156            // Otherwise we'll use Convert.ChangeType on primitives, except we
 157            // don't want to turn bools to/from numbers, strings to/from other
 158            // types, or cast doubles to integral types
 199159            bool canChange =
 199160                type.IsPrimitive &&
 199161                !(value is bool) && type != typeof(bool) &&
 199162                !(value is string) && type != typeof(string) &&
 199163                (!(value is double) || (type != typeof(int) && type != typeof(long)));
 199164            if (canChange)
 165            {
 61166                value = Convert.ChangeType(value, type, CultureInfo.InvariantCulture);
 167            }
 168
 182169            return value;
 170        }
 171    }
 172}

C:\Git\azure-sdk-for-net\sdk\search\Azure.Search.Documents\src\SearchDocument\SearchDocument.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections.Generic;
 6using System.IO;
 7using System.Text;
 8using System.Text.Json;
 9using System.Text.Json.Serialization;
 10using Azure.Core;
 11#if EXPERIMENTAL_SPATIAL
 12using Azure.Core.Spatial;
 13#endif
 14
 15namespace Azure.Search.Documents.Models
 16{
 17    /// <summary>
 18    /// Represents an untyped document returned from a search or document
 19    /// lookup.  It can be accessed as either a dynamic object or a dictionary.
 20    /// </summary>
 21    [JsonConverter(typeof(SearchDocumentConverter))]
 22    public partial class SearchDocument
 23#if EXPERIMENTAL_DYNAMIC
 24        : DynamicData
 25#endif
 26    {
 27        /// <summary>
 28        /// Initializes a new instance of the SearchDocument class.
 29        /// </summary>
 5155430        public SearchDocument() : this(null) { }
 31
 32#if EXPERIMENTAL_DYNAMIC
 33        /// <summary>
 34        /// Initializes a new instance of the SearchDocument class with initial
 35        /// values.
 36        /// </summary>
 37        /// <param name="values">Initial values of the document.</param>
 38        public SearchDocument(IDictionary<string, object> values) : base(values) { }
 39#else
 40        /// <summary>
 41        /// Initializes a new instance of the SearchDocument class with initial
 42        /// values.
 43        /// </summary>
 44        /// <param name="values">Initial values of the document.</param>
 2577745        public SearchDocument(IDictionary<string, object> values) =>
 2577746            _values = values != null ?
 2577747                new Dictionary<string, object>(values) :
 2577748                new Dictionary<string, object>();
 49#endif
 50
 51        /// <summary>
 52        /// Get the value of a <see cref="SearchDocument"/>'s
 53        /// <see cref="Nullable{Boolean}"/> property called
 54        /// <paramref name="key"/>.
 55        /// </summary>
 56        /// <param name="key">The name of the property.</param>
 57        /// <returns>The value of the property.</returns>
 2658        public bool? GetBoolean(string key) => GetValue<bool?>(key);
 59
 60        /// <summary>
 61        /// Get the value of a <see cref="SearchDocument"/>'s
 62        /// <see cref="Boolean"/> collection property called
 63        /// <paramref name="key"/>.
 64        /// </summary>
 65        /// <param name="key">The name of the property.</param>
 66        /// <returns>The value of the property.</returns>
 1367        public IReadOnlyList<bool> GetBooleanCollection(string key) => GetValue<bool[]>(key);
 68
 69        /// <summary>
 70        /// Get the value of a <see cref="SearchDocument"/>'s
 71        /// <see cref="Nullable{Int32}"/> property called
 72        /// <paramref name="key"/>.
 73        /// </summary>
 74        /// <param name="key">The name of the property.</param>
 75        /// <returns>The value of the property.</returns>
 3876        public int? GetInt32(string key) => GetValue<int?>(key);
 77
 78        /// <summary>
 79        /// Get the value of a <see cref="SearchDocument"/>'s
 80        /// <see cref="Int32"/> collection property called
 81        /// <paramref name="key"/>.
 82        /// </summary>
 83        /// <param name="key">The name of the property.</param>
 84        /// <returns>The value of the property.</returns>
 1685        public IReadOnlyList<int> GetInt32Collection(string key) => GetValue<int[]>(key);
 86
 87        /// <summary>
 88        /// Get the value of a <see cref="SearchDocument"/>'s
 89        /// <see cref="Nullable{Int64}"/> property called
 90        /// <paramref name="key"/>.
 91        /// </summary>
 92        /// <param name="key">The name of the property.</param>
 93        /// <returns>The value of the property.</returns>
 4694        public long? GetInt64(string key) => GetValue<long?>(key);
 95
 96        /// <summary>
 97        /// Get the value of a <see cref="SearchDocument"/>'s
 98        /// <see cref="Int64"/> collection property called
 99        /// <paramref name="key"/>.
 100        /// </summary>
 101        /// <param name="key">The name of the property.</param>
 102        /// <returns>The value of the property.</returns>
 17103        public IReadOnlyList<long> GetInt64Collection(string key) => GetValue<long[]>(key);
 104
 105        /// <summary>
 106        /// Get the value of a <see cref="SearchDocument"/>'s
 107        /// <see cref="Nullable{Double}"/> property called
 108        /// <paramref name="key"/>.
 109        /// </summary>
 110        /// <param name="key">The name of the property.</param>
 111        /// <returns>The value of the property.</returns>
 64112        public double? GetDouble(string key) => GetValue<double?>(key);
 113
 114        /// <summary>
 115        /// Get the value of a <see cref="SearchDocument"/>'s
 116        /// <see cref="Double"/> collection property called
 117        /// <paramref name="key"/>.
 118        /// </summary>
 119        /// <param name="key">The name of the property.</param>
 120        /// <returns>The value of the property.</returns>
 13121        public IReadOnlyList<double> GetDoubleCollection(string key) => GetValue<double[]>(key);
 122
 123        /// <summary>
 124        /// Get the value of a <see cref="SearchDocument"/>'s
 125        /// <see cref="Nullable{DateTimeOffset}"/> property called
 126        /// <paramref name="key"/>.
 127        /// </summary>
 128        /// <param name="key">The name of the property.</param>
 129        /// <returns>The value of the property.</returns>
 42130        public DateTimeOffset? GetDateTimeOffset(string key) => GetValue<DateTimeOffset?>(key);
 131
 132        /// <summary>
 133        /// Get the value of a <see cref="SearchDocument"/>'s
 134        /// <see cref="DateTimeOffset"/> collection property called
 135        /// <paramref name="key"/>.
 136        /// </summary>
 137        /// <param name="key">The name of the property.</param>
 138        /// <returns>The value of the property.</returns>
 13139        public IReadOnlyList<DateTimeOffset> GetDateTimeOffsetCollection(string key) => GetValue<DateTimeOffset[]>(key);
 140
 141        /// <summary>
 142        /// Get the value of a <see cref="SearchDocument"/>'s
 143        /// <see cref="String"/> property called
 144        /// <paramref name="key"/>.
 145        /// </summary>
 146        /// <param name="key">The name of the property.</param>
 147        /// <returns>The value of the property.</returns>
 17148        public string GetString(string key) => GetValue<string>(key);
 149
 150        /// <summary>
 151        /// Get the value of a <see cref="SearchDocument"/>'s
 152        /// <see cref="String"/> collection property called
 153        /// <paramref name="key"/>.
 154        /// </summary>
 155        /// <param name="key">The name of the property.</param>
 156        /// <returns>The value of the property.</returns>
 13157        public IReadOnlyList<string> GetStringCollection(string key) => GetValue<string[]>(key);
 158
 159#if EXPERIMENTAL_SPATIAL
 160        /// <summary>
 161        /// Get the value of a <see cref="SearchDocument"/>'s
 162        /// <see cref="PointGeometry"/> property called
 163        /// <paramref name="key"/>.
 164        /// </summary>
 165        /// <param name="key">The name of the property.</param>
 166        /// <returns>The value of the property.</returns>
 167        public PointGeometry GetPoint(string key) => GetValue<PointGeometry>(key);
 168
 169        /// <summary>
 170        /// Get the value of a <see cref="SearchDocument"/>'s
 171        /// <see cref="PointGeometry"/> collection property called
 172        /// <paramref name="key"/>.
 173        /// </summary>
 174        /// <param name="key">The name of the property.</param>
 175        /// <returns>The value of the property.</returns>
 176        public IReadOnlyList<PointGeometry> GetPointCollection(string key) => GetValue<PointGeometry[]>(key);
 177#endif
 178
 179        /// <summary>
 180        /// Get the value of a <see cref="SearchDocument"/>'s
 181        /// complex <see cref="SearchDocument"/> property called
 182        /// <paramref name="key"/>.
 183        /// </summary>
 184        /// <param name="key">The name of the property.</param>
 185        /// <returns>The value of the property.</returns>
 18186        public SearchDocument GetObject(string key) => GetValue<SearchDocument>(key);
 187
 188        /// <summary>
 189        /// Get the value of a <see cref="SearchDocument"/>'s
 190        /// complex <see cref="SearchDocument"/> collection property called
 191        /// <paramref name="key"/>.
 192        /// </summary>
 193        /// <param name="key">The name of the property.</param>
 194        /// <returns>The value of the property.</returns>
 15195        public IReadOnlyList<SearchDocument> GetObjectCollection(string key) => GetValue<SearchDocument[]>(key);
 196
 197        /// <inheritdoc />
 198        public override string ToString()
 199        {
 200            // Write the document as JSON.  This is expensive, but helpful.
 0201            using var stream = new MemoryStream();
 0202            using var writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true });
 0203            JsonSerialization.WriteSearchDocument(writer, this, JsonSerialization.SerializerOptions);
 0204            writer.Flush();
 0205            return Encoding.UTF8.GetString(stream.ToArray());
 0206        }
 207    }
 208}

C:\Git\azure-sdk-for-net\sdk\search\Azure.Search.Documents\src\SearchDocument\SearchDocument.Dictionary.cs

#LineLine coverage
 1// Copyright (c) Microsoft Corporation. All rights reserved.
 2// Licensed under the MIT License.
 3
 4using System;
 5using System.Collections;
 6using System.Collections.Generic;
 7
 8// This logic belongs in DynamicData, but they may not ship at the same time
 9// so we optionally compile a version of it into SearchDocument.
 10#if EXPERIMENTAL_DYNAMIC
 11namespace Azure.Core
 12{
 13    public partial class DynamicData
 14#else
 15namespace Azure.Search.Documents.Models
 16{
 17    public partial class SearchDocument
 18#endif
 19        : IDictionary<string, object>
 20    {
 21        /// <inheritdoc />
 22        public object this[string key]
 23        {
 2679524            get => GetValue(key);
 2754825            set => SetValue(key, value);
 26        }
 27
 28        /// <inheritdoc />
 29        public bool TryGetValue(string key, out object value) =>
 030            TryGetValue(key, typeof(object), out value);
 31
 32        /// <inheritdoc />
 1677533        public ICollection<string> Keys => _values.Keys;
 34
 35        /// <inheritdoc />
 036        ICollection<object> IDictionary<string, object>.Values => _values.Values;
 37
 38        /// <inheritdoc />
 039        public int Count => _values.Count;
 40
 41        /// <inheritdoc />
 042        bool ICollection<KeyValuePair<string, object>>.IsReadOnly => _values.IsReadOnly;
 43
 44        /// <inheritdoc />
 045        public void Add(string key, object value) => SetValue(key, value);
 46
 47        /// <inheritdoc />
 048        public bool ContainsKey(string key) => _values.ContainsKey(key);
 49
 50        /// <inheritdoc />
 51        void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item) =>
 052            SetValue(item.Key, item.Value);
 53
 54        /// <inheritdoc />
 55        bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item) =>
 056            _values.Contains(item);
 57
 58        /// <inheritdoc />
 59        void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex) =>
 060            _values.CopyTo(array, arrayIndex);
 61
 62        /// <inheritdoc />
 63        public IEnumerator<KeyValuePair<string, object>> GetEnumerator() =>
 5464            _values.GetEnumerator();
 65
 66        /// <inheritdoc />
 4467        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 68
 69        /// <inheritdoc />
 070        public bool Remove(string key) => _values.Remove(key);
 71
 72        /// <inheritdoc />
 73        bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item) =>
 074            _values.Remove(item);
 75
 76        /// <inheritdoc />
 077        public void Clear() => _values.Clear();
 78    }
 79}