LCOV - code coverage report
Current view: top level - Cqrs.WebApi/Controllers - System.Web.Helpers.cs Hit Total Coverage
Test: doc-coverage.info Lines: 0 30 0.0 %
Date: 2017-07-26

          Line data    Source code
       1             : // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
       2             : 
       3             : using System.Collections;
       4             : using System.Collections.Generic;
       5             : using System.IO;
       6             : using System.Web.Script.Serialization;
       7             : using System.Diagnostics;
       8             : using System.Diagnostics.CodeAnalysis;
       9             : using System.Dynamic;
      10             : using System.Globalization;
      11             : using System.Linq;
      12             : using System.Linq.Expressions;
      13             : using System.Runtime.CompilerServices;
      14             : using System.Web.Helpers.Resources;
      15             : using Microsoft.CSharp.RuntimeBinder;
      16             : 
      17             : // ReSharper disable once CheckNamespace
      18             : namespace System.Web.Helpers
      19             : {
      20             :         public static class Json
      21           0 :         {
      22             :                 private static readonly JavaScriptSerializer _serializer = CreateSerializer();
      23             : 
      24           0 :                 public static string Encode(object value)
      25             :                 {
      26             :                         // Serialize our dynamic array type as an array
      27             :                         DynamicJsonArray jsonArray = value as DynamicJsonArray;
      28             :                         if (jsonArray != null)
      29             :                         {
      30             :                                 return _serializer.Serialize((object[])jsonArray);
      31             :                         }
      32             : 
      33             :                         return _serializer.Serialize(value);
      34             :                 }
      35             : 
      36           0 :                 public static void Write(object value, TextWriter writer)
      37             :                 {
      38             :                         writer.Write(_serializer.Serialize(value));
      39             :                 }
      40             : 
      41           0 :                 public static dynamic Decode(string value)
      42             :                 {
      43             :                         return WrapObject(_serializer.DeserializeObject(value));
      44             :                 }
      45             : 
      46           0 :                 public static dynamic Decode(string value, Type targetType)
      47             :                 {
      48             :                         return WrapObject(_serializer.Deserialize(value, targetType));
      49             :                 }
      50             : 
      51           0 :                 public static T Decode<T>(string value)
      52             :                 {
      53             :                         return _serializer.Deserialize<T>(value);
      54             :                 }
      55             : 
      56             :                 private static JavaScriptSerializer CreateSerializer()
      57             :                 {
      58             :                         JavaScriptSerializer serializer = new JavaScriptSerializer();
      59             :                         serializer.RegisterConverters(new[] { new DynamicJavaScriptConverter() });
      60             :                         return serializer;
      61             :                 }
      62             : 
      63             :                 internal static dynamic WrapObject(object value)
      64             :                 {
      65             :                         // The JavaScriptSerializer returns IDictionary<string, object> for objects
      66             :                         // and object[] for arrays, so we wrap those in different dynamic objects
      67             :                         // so we can access the object graph using dynamic
      68             :                         var dictionaryValues = value as IDictionary<string, object>;
      69             :                         if (dictionaryValues != null)
      70             :                         {
      71             :                                 return new DynamicJsonObject(dictionaryValues);
      72             :                         }
      73             : 
      74             :                         var arrayValues = value as object[];
      75             :                         if (arrayValues != null)
      76             :                         {
      77             :                                 return new DynamicJsonArray(arrayValues);
      78             :                         }
      79             : 
      80             :                         return value;
      81             :                 }
      82             :         }
      83             : 
      84             :         // REVIEW: Consider implementing ICustomTypeDescriptor and IDictionary<string, object>
      85             :         public class DynamicJsonObject : DynamicObject
      86           0 :         {
      87             :                 private readonly IDictionary<string, object> _values;
      88             : 
      89           0 :                 public DynamicJsonObject(IDictionary<string, object> values)
      90             :                 {
      91             :                         Debug.Assert(values != null);
      92             :                         _values = values.ToDictionary(p => p.Key, p => Json.WrapObject(p.Value),
      93             :                                                                                   StringComparer.OrdinalIgnoreCase);
      94             :                 }
      95             : 
      96           0 :                 public override bool TryConvert(ConvertBinder binder, out object result)
      97             :                 {
      98             :                         result = null;
      99             :                         if (binder.Type.IsAssignableFrom(_values.GetType()))
     100             :                         {
     101             :                                 result = _values;
     102             :                         }
     103             :                         else
     104             :                         {
     105             :                                 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, HelpersResources.Json_UnableToConvertType, binder.Type));
     106             :                         }
     107             :                         return true;
     108             :                 }
     109             : 
     110           0 :                 public override bool TryGetMember(GetMemberBinder binder, out object result)
     111             :                 {
     112             :                         result = GetValue(binder.Name);
     113             :                         return true;
     114             :                 }
     115             : 
     116           0 :                 public override bool TrySetMember(SetMemberBinder binder, object value)
     117             :                 {
     118             :                         _values[binder.Name] = Json.WrapObject(value);
     119             :                         return true;
     120             :                 }
     121             : 
     122           0 :                 public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value)
     123             :                 {
     124             :                         string key = GetKey(indexes);
     125             :                         if (!String.IsNullOrEmpty(key))
     126             :                         {
     127             :                                 _values[key] = Json.WrapObject(value);
     128             :                         }
     129             :                         return true;
     130             :                 }
     131             : 
     132           0 :                 public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)
     133             :                 {
     134             :                         string key = GetKey(indexes);
     135             :                         result = null;
     136             :                         if (!String.IsNullOrEmpty(key))
     137             :                         {
     138             :                                 result = GetValue(key);
     139             :                         }
     140             :                         return true;
     141             :                 }
     142             : 
     143             :                 private static string GetKey(object[] indexes)
     144             :                 {
     145             :                         if (indexes.Length == 1)
     146             :                         {
     147             :                                 return (string)indexes[0];
     148             :                         }
     149             :                         // REVIEW: Should this throw?
     150             :                         return null;
     151             :                 }
     152             : 
     153           0 :                 public override IEnumerable<string> GetDynamicMemberNames()
     154             :                 {
     155             :                         return _values.Keys;
     156             :                 }
     157             : 
     158             :                 private object GetValue(string name)
     159             :                 {
     160             :                         object result;
     161             :                         if (_values.TryGetValue(name, out result))
     162             :                         {
     163             :                                 return result;
     164             :                         }
     165             :                         return null;
     166             :                 }
     167             :         }
     168             : 
     169             :         [SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification = "This class isn't meant to be used directly")]
     170             :         public class DynamicJsonArray : DynamicObject, IEnumerable<object>
     171           0 :         {
     172             :                 private readonly object[] _arrayValues;
     173             : 
     174           0 :                 public DynamicJsonArray(object[] arrayValues)
     175             :                 {
     176             :                         Debug.Assert(arrayValues != null);
     177             :                         _arrayValues = arrayValues.Select(Json.WrapObject).ToArray();
     178             :                 }
     179             : 
     180             :                 public int Length
     181             :                 {
     182             :                         get { return _arrayValues.Length; }
     183             :                 }
     184             : 
     185             :                 public dynamic this[int index]
     186             :                 {
     187             :                         get { return _arrayValues[index]; }
     188             :                         set { _arrayValues[index] = Json.WrapObject(value); }
     189             :                 }
     190             : 
     191           0 :                 public override bool TryConvert(ConvertBinder binder, out object result)
     192             :                 {
     193             :                         if (_arrayValues.GetType().IsAssignableFrom(binder.Type))
     194             :                         {
     195             :                                 result = _arrayValues;
     196             :                                 return true;
     197             :                         }
     198             :                         return base.TryConvert(binder, out result);
     199             :                 }
     200             : 
     201           0 :                 public override bool TryGetMember(GetMemberBinder binder, out object result)
     202             :                 {
     203             :                         // Testing for members should never throw. This is important when dealing with
     204             :                         // services that return different json results. Testing for a member shouldn't throw,
     205             :                         // it should just return null (or undefined)
     206             :                         result = null;
     207             :                         return true;
     208             :                 }
     209             : 
     210           0 :                 public IEnumerator GetEnumerator()
     211             :                 {
     212             :                         return _arrayValues.GetEnumerator();
     213             :                 }
     214             : 
     215             :                 private IEnumerable<object> GetEnumerable()
     216             :                 {
     217             :                         return _arrayValues.AsEnumerable();
     218             :                 }
     219             : 
     220             :                 IEnumerator<object> IEnumerable<object>.GetEnumerator()
     221             :                 {
     222             :                         return GetEnumerable().GetEnumerator();
     223             :                 }
     224             : 
     225             :                 [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "This class isn't meant to be used directly")]
     226           0 :                 public static implicit operator object[](DynamicJsonArray obj)
     227             :                 {
     228             :                         return obj._arrayValues;
     229             :                 }
     230             : 
     231             :                 [SuppressMessage("Microsoft.Usage", "CA2225:OperatorOverloadsHaveNamedAlternates", Justification = "This class isn't meant to be used directly")]
     232           0 :                 public static implicit operator Array(DynamicJsonArray obj)
     233             :                 {
     234             :                         return obj._arrayValues;
     235             :                 }
     236             :         }
     237             : 
     238             :         /// <summary>
     239             :         /// Converter that knows how to get the member values from a dynamic object.
     240             :         /// </summary>
     241             :         internal class DynamicJavaScriptConverter : JavaScriptConverter
     242             :         {
     243             :                 public override IEnumerable<Type> SupportedTypes
     244             :                 {
     245             :                         get
     246             :                         {
     247             :                                 // REVIEW: For some reason the converters don't pick up interfaces
     248             :                                 yield return typeof(IDynamicMetaObjectProvider);
     249             :                                 yield return typeof(DynamicObject);
     250             :                         }
     251             :                 }
     252             : 
     253           0 :                 public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
     254             :                 {
     255             :                         throw new NotSupportedException();
     256             :                 }
     257             : 
     258           0 :                 public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
     259             :                 {
     260             :                         var values = new Dictionary<string, object>(StringComparer.OrdinalIgnoreCase);
     261             :                         var memberNames = DynamicHelper.GetMemberNames(obj);
     262             : 
     263             :                         // This should never happen
     264             :                         Debug.Assert(memberNames != null);
     265             : 
     266             :                         // Get the value for each member in the dynamic object
     267             :                         foreach (string memberName in memberNames)
     268             :                         {
     269             :                                 values[memberName] = DynamicHelper.GetMemberValue(obj, memberName);
     270             :                         }
     271             : 
     272             :                         return values;
     273             :                 }
     274             :         }
     275             : 
     276             :         /// <summary>
     277             :         /// Helper to evaluate different method on dynamic objects
     278             :         /// </summary>
     279             :         internal static class DynamicHelper
     280             :         {
     281             :                 // We must pass in "object" instead of "dynamic" for the target dynamic object because if we use dynamic, the compiler will
     282             :                 // convert the call to this helper into a dynamic expression, even though we don't need it to be.  Since this class is internal,
     283             :                 // it cannot be accessed from a dynamic expression and thus we get errors.
     284             : 
     285             :                 // Dev10 Bug 914027 - Changed the first parameter from dynamic to object, see comment at top for details
     286           0 :                 public static bool TryGetMemberValue(object obj, string memberName, out object result)
     287             :                 {
     288             :                         try
     289             :                         {
     290             :                                 result = GetMemberValue(obj, memberName);
     291             :                                 return true;
     292             :                         }
     293             :                         catch (RuntimeBinderException)
     294             :                         {
     295             :                         }
     296             :                         catch (RuntimeBinderInternalCompilerException)
     297             :                         {
     298             :                         }
     299             : 
     300             :                         // We catch the C# specific runtime binder exceptions since we're using the C# binder in this case
     301             :                         result = null;
     302             :                         return false;
     303             :                 }
     304             : 
     305             :                 // Dev10 Bug 914027 - Changed the first parameter from dynamic to object, see comment at top for details
     306             :                 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We want to swallow exceptions that happen during runtime binding")]
     307           0 :                 public static bool TryGetMemberValue(object obj, GetMemberBinder binder, out object result)
     308             :                 {
     309             :                         try
     310             :                         {
     311             :                                 // VB us an instance of GetBinderAdapter that does not implement FallbackGetMemeber. This causes lookup of property expressions on dynamic objects to fail.
     312             :                                 // Since all types are private to the assembly, we assume that as long as they belong to CSharp runtime, it is the right one. 
     313             :                                 if (typeof(Binder).Assembly.Equals(binder.GetType().Assembly))
     314             :                                 {
     315             :                                         // Only use the binder if its a C# binder.
     316             :                                         result = GetMemberValue(obj, binder);
     317             :                                 }
     318             :                                 else
     319             :                                 {
     320             :                                         result = GetMemberValue(obj, binder.Name);
     321             :                                 }
     322             :                                 return true;
     323             :                         }
     324             :                         catch
     325             :                         {
     326             :                                 result = null;
     327             :                                 return false;
     328             :                         }
     329             :                 }
     330             : 
     331             :                 // Dev10 Bug 914027 - Changed the first parameter from dynamic to object, see comment at top for details
     332           0 :                 public static object GetMemberValue(object obj, string memberName)
     333             :                 {
     334             :                         var callSite = GetMemberAccessCallSite(memberName);
     335             :                         return callSite.Target(callSite, obj);
     336             :                 }
     337             : 
     338             :                 // Dev10 Bug 914027 - Changed the first parameter from dynamic to object, see comment at top for details
     339           0 :                 public static object GetMemberValue(object obj, GetMemberBinder binder)
     340             :                 {
     341             :                         var callSite = GetMemberAccessCallSite(binder);
     342             :                         return callSite.Target(callSite, obj);
     343             :                 }
     344             : 
     345             :                 // dynamic d = new object();
     346             :                 // object s = d.Name;
     347             :                 // The following code gets generated for this expression:
     348             :                 // callSite = CallSite<Func<CallSite, object, object>>.Create(Binder.GetMember(CSharpBinderFlags.None, "Name", typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));
     349             :                 // callSite.Target(callSite, d);
     350             :                 // typeof(Program) is the containing type of the dynamic operation.
     351             :                 // Dev10 Bug 914027 - Changed the callsite's target parameter from dynamic to object, see comment at top for details
     352           0 :                 public static CallSite<Func<CallSite, object, object>> GetMemberAccessCallSite(string memberName)
     353             :                 {
     354             :                         var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, typeof(DynamicHelper), new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
     355             :                         return GetMemberAccessCallSite(binder);
     356             :                 }
     357             : 
     358             :                 // Dev10 Bug 914027 - Changed the callsite's target parameter from dynamic to object, see comment at top for details
     359           0 :                 public static CallSite<Func<CallSite, object, object>> GetMemberAccessCallSite(CallSiteBinder binder)
     360             :                 {
     361             :                         return CallSite<Func<CallSite, object, object>>.Create(binder);
     362             :                 }
     363             : 
     364             :                 // Dev10 Bug 914027 - Changed the first parameter from dynamic to object, see comment at top for details
     365           0 :                 public static IEnumerable<string> GetMemberNames(object obj)
     366             :                 {
     367             :                         var provider = obj as IDynamicMetaObjectProvider;
     368             :                         Debug.Assert(provider != null, "obj doesn't implement IDynamicMetaObjectProvider");
     369             : 
     370             :                         Expression parameter = Expression.Parameter(typeof(object));
     371             :                         return provider.GetMetaObject(parameter).GetDynamicMemberNames();
     372             :                 }
     373             :         }
     374             : }

Generated by: LCOV version 1.10