Exemplo n.º 1
0
        public PropertyValueConverter(
            int maximumDestructuringDepth, 
            int maximumStringLength,
            int maximumCollectionCount,
            IEnumerable<Type> additionalScalarTypes,
            IEnumerable<IDestructuringPolicy> additionalDestructuringPolicies,
            bool propagateExceptions)
        {
            if (additionalScalarTypes == null) throw new ArgumentNullException(nameof(additionalScalarTypes));
            if (additionalDestructuringPolicies == null) throw new ArgumentNullException(nameof(additionalDestructuringPolicies));
            if (maximumDestructuringDepth < 0) throw new ArgumentOutOfRangeException(nameof(maximumDestructuringDepth));
            if (maximumStringLength < 2) throw new ArgumentOutOfRangeException(nameof(maximumStringLength));
            if (maximumCollectionCount < 1) throw new ArgumentOutOfRangeException(nameof(maximumCollectionCount));
            
            _propagateExceptions = propagateExceptions;
            _maximumStringLength = maximumStringLength;
            _maximumCollectionCount = maximumCollectionCount;

            _scalarConversionPolicies = new IScalarConversionPolicy[]
            {
                new SimpleScalarConversionPolicy(BuiltInScalarTypes.Concat(additionalScalarTypes)),
                new EnumScalarConversionPolicy(),
                new ByteArrayScalarConversionPolicy()
            };

            _destructuringPolicies = additionalDestructuringPolicies
                .Concat(new IDestructuringPolicy []
                {
                    new DelegateDestructuringPolicy(),
                    new ReflectionTypesScalarDestructuringPolicy()
                })
                .ToArray();

            _depthLimiter = new DepthLimiter(maximumDestructuringDepth, this);
        }
            private Expression VisitIncludeCall(IncludeMethodCallExpression includeCall)
            {
                var retrievals = includeCall.Retrievals;
                var canRecurse = DepthLimiter.CanRecurse(includeCall.ElementType);

                using (DepthLimiter.Enter(includeCall.ElementType))
                {
                    if (canRecurse)
                    {
                        retrievals = new ReadOnlyCollection <Expression>(
                            retrievals
                            .Concat(
                                Owner.GetRetrievalsCore(includeCall.ElementType)
                                )
                            .ToArray()
                            );
                    }

                    Logger.Debug(
                        "RetrievalAppendingVisitor retrievals to include: {Retrievals}",
                        retrievals
                        );

                    if (retrievals.Any())
                    {
                        var updated = includeCall.Update(
                            Visit(includeCall.Object),
                            Visit(retrievals)
                            );

                        return(updated.Reduce());
                    }

                    return(Visit(includeCall.Object));
                }
            }
Exemplo n.º 3
0
        LogEventPropertyValue CreatePropertyValue(object value, Destructuring destructuring, int depth)
        {
            if (value == null)
            {
                return(new ScalarValue(null));
            }

            if (destructuring == Destructuring.Stringify)
            {
                return(Stringify(value));
            }

            if (destructuring == Destructuring.Destructure)
            {
                if (value is string stringValue)
                {
                    value = TruncateIfNecessary(stringValue);
                }
            }

            if (value is string)
            {
                return(new ScalarValue(value));
            }

            foreach (var scalarConversionPolicy in _scalarConversionPolicies)
            {
                if (scalarConversionPolicy.TryConvertToScalar(value, out var converted))
                {
                    return(converted);
                }
            }

            DepthLimiter.SetCurrentDepth(depth);

            if (destructuring == Destructuring.Destructure)
            {
                foreach (var destructuringPolicy in _destructuringPolicies)
                {
                    if (destructuringPolicy.TryDestructure(value, _depthLimiter, out var result))
                    {
                        return(result);
                    }
                }
            }

            var valueType = value.GetType();

            if (TryConvertEnumerable(value, destructuring, valueType, out var enumerableResult))
            {
                return(enumerableResult);
            }

            if (TryConvertValueTuple(value, destructuring, valueType, out var tupleResult))
            {
                return(tupleResult);
            }

            if (TryConvertCompilerGeneratedType(value, destructuring, valueType, out var compilerGeneratedResult))
            {
                return(compilerGeneratedResult);
            }

            return(new ScalarValue(value.ToString() ?? ""));
        }
 public RetrievalAppendingVisitor(ClientObjectQueryProcessor owner)
 {
     Owner = owner;
     DepthLimiter = new DepthLimiter(owner);
 }
        TemplatePropertyValue CreatePropertyValue(object value, Destructuring destructuring, int depth)
        {
            if (value == null)
            {
                return(new ScalarValue(null));
            }

            if (destructuring == Destructuring.Stringify)
            {
                return(new ScalarValue(value.ToString()));
            }

            var valueType = value.GetType();
            var limiter   = new DepthLimiter(depth, _maximumDestructuringDepth, this);

            foreach (var scalarConversionPolicy in _scalarConversionPolicies)
            {
                ScalarValue converted;
                if (scalarConversionPolicy.TryConvertToScalar(value, limiter, out converted))
                {
                    return(converted);
                }
            }

            if (destructuring == Destructuring.Destructure)
            {
                foreach (var destructuringPolicy in _destructuringPolicies)
                {
                    TemplatePropertyValue result;
                    if (destructuringPolicy.TryDestructure(value, limiter, out result))
                    {
                        return(result);
                    }
                }
            }

            var enumerable = value as IEnumerable;

            if (enumerable != null)
            {
                // Only dictionaries with 'scalar' keys are permitted, as
                // more complex keys may not serialize to unique values for
                // representation in sinks. This check strengthens the expectation
                // that resulting dictionary is representable in JSON as well
                // as richer formats (e.g. XML, .NET type-aware...).
                // Only actual dictionaries are supported, as arbitrary types
                // can implement multiple IDictionary interfaces and thus introduce
                // multiple different interpretations.
                if (IsValueTypeDictionary(valueType))
                {
                    Func <object, object> getKey;
                    Func <object, object> getValue;
#if !REFLECTION_API_EVOLVED // https://blogs.msdn.microsoft.com/dotnet/2012/08/28/evolving-the-reflection-api/
                    PropertyInfo keyProperty = null;
                    getKey = o => (keyProperty ?? (keyProperty = o.GetType().GetProperty("Key"))).GetValue(o, null);
                    PropertyInfo valueProperty = null;
                    getValue = o => (valueProperty ?? (valueProperty = o.GetType().GetProperty("Value"))).GetValue(o, null);
#else
                    PropertyInfo keyProperty = null;
                    getKey = o => (keyProperty ?? (keyProperty = o.GetType().GetRuntimeProperty("Key"))).GetValue(o);
                    PropertyInfo valueProperty = null;
                    getValue = o => (valueProperty ?? (valueProperty = o.GetType().GetRuntimeProperty("Value"))).GetValue(o);
#endif

                    // TODO: stop using LINQ
                    return(new DictionaryValue(enumerable
                                               .Cast <object>()
                                               .Where(o => o != null)
                                               .Select(o => new { Key = getKey(o), Value = getValue(o) })
                                               .Select(o => new KeyValuePair <ScalarValue, TemplatePropertyValue>(
                                                           key: (ScalarValue)limiter.CreatePropertyValue(o.Key, destructuring),
                                                           value: limiter.CreatePropertyValue(o.Value, destructuring))
                                                       )
                                               ));
                }

                return(new SequenceValue(
                           enumerable.Cast <object>().Select(o => limiter.CreatePropertyValue(o, destructuring))));
            }

            if (destructuring == Destructuring.Destructure)
            {
                var type    = value.GetType();
                var typeTag = type.Name;
#if REFLECTION_API_EVOLVED
                if (typeTag.Length <= 0 || IsCompilerGeneratedType(type))
                {
                    typeTag = null;
                }
#else
                if (typeTag.Length <= 0 || !char.IsLetter(typeTag[0]))
                {
                    typeTag = null;
                }
#endif
                return(new StructureValue(GetProperties(value, limiter), typeTag));
            }

            return(new ScalarValue(value.ToString()));
        }
        TemplatePropertyValue CreatePropertyValue(object value, Destructuring destructuring, int depth)
        {
            if (value == null)
                return new ScalarValue(null);

            if (destructuring == Destructuring.Stringify)
                return new ScalarValue(value.ToString());

            var valueType = value.GetType();
            var limiter = new DepthLimiter(depth, _maximumDestructuringDepth, this);

            foreach (var scalarConversionPolicy in _scalarConversionPolicies)
            {
                ScalarValue converted;
                if (scalarConversionPolicy.TryConvertToScalar(value, limiter, out converted))
                    return converted;
            }

            if (destructuring == Destructuring.Destructure)
            {
                foreach (var destructuringPolicy in _destructuringPolicies)
                {
                    TemplatePropertyValue result;
                    if (destructuringPolicy.TryDestructure(value, limiter, out result))
                        return result;
                }
            }

            #region IEnumerable->SequenceValue|DictionaryValue

            var enumerable = value as IEnumerable;
            if (enumerable != null)
            {
                // Only dictionaries with 'scalar' keys are permitted, as
                // more complex keys may not serialize to unique values for
                // representation in sinks. This check strengthens the expectation
                // that resulting dictionary is representable in JSON as well
                // as richer formats (e.g. XML, .NET type-aware...).
                // Only actual dictionaries are supported, as arbitrary types
                // can implement multiple IDictionary interfaces and thus introduce
                // multiple different interpretations.
                if (IsValueTypeDictionary(valueType))
                {
                    Func<object, object> getKey;
                    Func<object, object> getValue;
            #if USE_REFLECTION_40
                    PropertyInfo keyProperty = null;
                    getKey = o => (keyProperty ?? (keyProperty = o.GetType().GetProperty("Key"))).GetValue(o, null);
                    PropertyInfo valueProperty = null;
                    getValue = o => (valueProperty ?? (valueProperty = o.GetType().GetProperty("Value"))).GetValue(o, null);
            #else
                    PropertyInfo keyProperty = null;
                    getKey = o => (keyProperty ?? (keyProperty = o.GetType().GetRuntimeProperty("Key"))).GetValue(o);
                    PropertyInfo valueProperty = null;
                    getValue = o => (valueProperty ?? (valueProperty = o.GetType().GetRuntimeProperty("Value"))).GetValue(o);
            #endif

                    return new DictionaryValue(enumerable
                        .Cast<object>()
                        .Where(o => o != null)
                        .Select(o => new { Key = getKey(o), Value = getValue(o) })
                        .Select(o => new KeyValuePair<ScalarValue, TemplatePropertyValue>(
                            key: (ScalarValue)limiter.CreatePropertyValue(o.Key, destructuring),
                            value: limiter.CreatePropertyValue(o.Value, destructuring))
                        )
                    );
                }

                return new SequenceValue(
                    enumerable.Cast<object>().Select(o => limiter.CreatePropertyValue(o, destructuring)));
            }

            #endregion

            if (destructuring == Destructuring.Destructure)
            {
                var typeTag = value.GetType().Name;
                if (typeTag.Length <= 0 || !char.IsLetter(typeTag[0]))
                    typeTag = null;

                return new StructureValue(GetProperties(value, limiter), typeTag);
            }

            return new ScalarValue(value.ToString());
        }
 public RetrievalAppendingVisitor(ClientObjectQueryProcessor owner)
 {
     Owner        = owner;
     DepthLimiter = new DepthLimiter(owner);
 }