1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. 2 3 using System.Collections.Generic; 4 using System.Diagnostics; 5 using System.Dynamic; 6 using System.Globalization; 7 using System.Linq; 8 using System.Web.Helpers.Resources; 9 10 namespace System.Web.Helpers 11 { 12 // REVIEW: Consider implementing ICustomTypeDescriptor and IDictionary<string, object> 13 public class DynamicJsonObject : DynamicObject 14 { 15 private readonly IDictionary<string, object> _values; 16 DynamicJsonObject(IDictionary<string, object> values)17 public DynamicJsonObject(IDictionary<string, object> values) 18 { 19 Debug.Assert(values != null); 20 _values = values.ToDictionary(p => p.Key, p => Json.WrapObject(p.Value), 21 StringComparer.OrdinalIgnoreCase); 22 } 23 TryConvert(ConvertBinder binder, out object result)24 public override bool TryConvert(ConvertBinder binder, out object result) 25 { 26 result = null; 27 if (binder.Type.IsAssignableFrom(_values.GetType())) 28 { 29 result = _values; 30 } 31 else 32 { 33 throw new InvalidOperationException(String.Format(CultureInfo.CurrentCulture, HelpersResources.Json_UnableToConvertType, binder.Type)); 34 } 35 return true; 36 } 37 TryGetMember(GetMemberBinder binder, out object result)38 public override bool TryGetMember(GetMemberBinder binder, out object result) 39 { 40 result = GetValue(binder.Name); 41 return true; 42 } 43 TrySetMember(SetMemberBinder binder, object value)44 public override bool TrySetMember(SetMemberBinder binder, object value) 45 { 46 _values[binder.Name] = Json.WrapObject(value); 47 return true; 48 } 49 TrySetIndex(SetIndexBinder binder, object[] indexes, object value)50 public override bool TrySetIndex(SetIndexBinder binder, object[] indexes, object value) 51 { 52 string key = GetKey(indexes); 53 if (!String.IsNullOrEmpty(key)) 54 { 55 _values[key] = Json.WrapObject(value); 56 } 57 return true; 58 } 59 TryGetIndex(GetIndexBinder binder, object[] indexes, out object result)60 public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) 61 { 62 string key = GetKey(indexes); 63 result = null; 64 if (!String.IsNullOrEmpty(key)) 65 { 66 result = GetValue(key); 67 } 68 return true; 69 } 70 GetKey(object[] indexes)71 private static string GetKey(object[] indexes) 72 { 73 if (indexes.Length == 1) 74 { 75 return (string)indexes[0]; 76 } 77 // REVIEW: Should this throw? 78 return null; 79 } 80 GetDynamicMemberNames()81 public override IEnumerable<string> GetDynamicMemberNames() 82 { 83 return _values.Keys; 84 } 85 GetValue(string name)86 private object GetValue(string name) 87 { 88 object result; 89 if (_values.TryGetValue(name, out result)) 90 { 91 return result; 92 } 93 return null; 94 } 95 } 96 } 97