private static object Deserialize(JsonSerializer serializer, JToken jtoken, ViewModelPropertyMap property, object existingValue) { if (property.JsonConverter != null && property.JsonConverter.CanRead && property.JsonConverter.CanConvert(property.Type)) { return(property.JsonConverter.ReadJson(jtoken.CreateReader(), property.Type, existingValue, serializer)); } else if (existingValue != null && property.Populate) { if (jtoken.Type == JTokenType.Null) { return(null); } else if (jtoken.Type == JTokenType.Object) { serializer.Converters.OfType <ViewModelJsonConverter>().First().Populate((JObject)jtoken, serializer, existingValue); return(existingValue); } else { serializer.Populate(jtoken.CreateReader(), existingValue); return(existingValue); } } else { if (property.Type.GetTypeInfo().IsValueType&& jtoken.Type == JTokenType.Null) { return(Activator.CreateInstance(property.Type)); } else { return(serializer.Deserialize(jtoken.CreateReader(), property.Type)); } } }
private void GenerateOptionsBlock(IList <Expression> block, ViewModelPropertyMap property, Dictionary <string, object> options, ParameterExpression writer) { block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WritePropertyName(property.Name + "$options"), writer)); block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteStartObject(), writer)); foreach (var option in options) { block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WritePropertyName(option.Key), writer)); switch (option.Key) { case CLIENT_EXTENDERS_KEY: { // declare 'clientExtenders' as the array of objects block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteStartArray(), writer)); foreach (var extender in property.ClientExtenders) { block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteStartObject(), writer)); block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WritePropertyName("name"), writer)); block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteValue(extender.Name), writer)); block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WritePropertyName("parameter"), writer)); block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteValue(extender.Parameter), writer)); block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteEndObject(), writer)); } block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteEndArray(), writer)); break; } default: // legacy code - direct { property : value } block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteValue(option.Value), writer)); break; } } block.Add(ExpressionUtils.Replace <JsonWriter>(w => w.WriteEndObject(), writer)); }
/// <summary> /// Gets the properties of the specified type. /// </summary> protected virtual IEnumerable <ViewModelPropertyMap> GetProperties(Type type) { foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name)) { if (property.GetCustomAttribute <JsonIgnoreAttribute>() != null) { continue; } var propertyMap = new ViewModelPropertyMap() { PropertyInfo = property, Name = property.Name, ViewModelProtection = ProtectMode.None, Type = property.PropertyType, TransferAfterPostback = property.GetMethod != null && property.GetMethod.IsPublic, TransferFirstRequest = property.GetMethod != null && property.GetMethod.IsPublic, TransferToServer = property.SetMethod != null && property.SetMethod.IsPublic, JsonConverter = GetJsonConverter(property), Populate = ViewModelJsonConverter.IsComplexType(property.PropertyType) && !ViewModelJsonConverter.IsEnumerable(property.PropertyType) && property.GetMethod != null }; foreach (ISerializationInfoAttribute attr in property.GetCustomAttributes().OfType <ISerializationInfoAttribute>()) { attr.SetOptions(propertyMap); } var bindAttribute = property.GetCustomAttribute <BindAttribute>(); if (bindAttribute != null) { propertyMap.Bind(bindAttribute.Direction); if (bindAttribute.Name != null) { propertyMap.Name = bindAttribute.Name; } } var viewModelProtectionAttribute = property.GetCustomAttribute <ProtectAttribute>(); if (viewModelProtectionAttribute != null) { propertyMap.ViewModelProtection = viewModelProtectionAttribute.Settings; } propertyMap.ClientExtenders = property.GetCustomAttributes <ClientExtenderAttribute>() .OrderBy(c => c.Order) .Select(extender => new ClientExtenderInfo() { Name = extender.Name, Parameter = extender.Parameter }) .ToList(); var validationAttributes = validationMetadataProvider.GetAttributesForProperty(property); propertyMap.ValidationRules = validationRuleTranslator.TranslateValidationRules(property, validationAttributes).ToList(); propertyMap.ValidateSettings(); yield return(propertyMap); } }
public static ViewModelPropertyMap Bind(this ViewModelPropertyMap property, Direction direction) { property.TransferAfterPostback = direction.HasFlag(Direction.ServerToClientPostback); property.TransferFirstRequest = direction.HasFlag(Direction.ServerToClientFirstRequest); property.TransferToServer = direction.HasFlag(Direction.ClientToServerNotInPostbackPath) || direction.HasFlag(Direction.ClientToServerInPostbackPath); property.TransferToServerOnlyInPath = !direction.HasFlag(Direction.ClientToServerNotInPostbackPath) && property.TransferToServer; return(property); }
/// <summary> /// Gets the properties of the specified type. /// </summary> protected virtual IEnumerable <ViewModelPropertyMap> GetProperties(Type type) { foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name)) { if (property.GetCustomAttribute <JsonIgnoreAttribute>() != null) { continue; } var propertyMap = new ViewModelPropertyMap() { PropertyInfo = property, Name = property.Name, ViewModelProtection = ProtectMode.None, Type = property.PropertyType, TransferAfterPostback = property.GetMethod != null && property.GetMethod.IsPublic, TransferFirstRequest = property.GetMethod != null && property.GetMethod.IsPublic, TransferToServer = property.SetMethod != null && property.SetMethod.IsPublic, JsonConverter = GetJsonConverter(property), Populate = ViewModelJsonConverter.IsComplexType(property.PropertyType) && !ViewModelJsonConverter.IsEnumerable(property.PropertyType) && property.GetMethod != null }; var bindAttribute = property.GetCustomAttribute <BindAttribute>(); if (bindAttribute != null) { propertyMap.TransferAfterPostback = bindAttribute.Direction.HasFlag(Direction.ServerToClientPostback); propertyMap.TransferFirstRequest = bindAttribute.Direction.HasFlag(Direction.ServerToClientFirstRequest); propertyMap.TransferToServer = bindAttribute.Direction.HasFlag(Direction.ClientToServerNotInPostbackPath) || bindAttribute.Direction.HasFlag(Direction.ClientToServerInPostbackPath); propertyMap.TransferToServerOnlyInPath = !bindAttribute.Direction.HasFlag(Direction.ClientToServerNotInPostbackPath) && propertyMap.TransferToServer; } var viewModelProtectionAttribute = property.GetCustomAttribute <ProtectAttribute>(); if (viewModelProtectionAttribute != null) { propertyMap.ViewModelProtection = viewModelProtectionAttribute.Settings; } var clientExtenderList = property.GetCustomAttributes <ClientExtenderAttribute>(); if (clientExtenderList.Any()) { clientExtenderList .OrderBy(c => c.Order) .ToList() .ForEach(extender => propertyMap.ClientExtenders.Add(new ClientExtenderInfo() { Name = extender.Name, Parameter = extender.Parameter })); } var validationAttributes = validationMetadataProvider.GetAttributesForProperty(property); propertyMap.ValidationRules = validationRuleTranslator.TranslateValidationRules(property, validationAttributes).ToList(); yield return(propertyMap); } }
private static void Serialize(JsonSerializer serializer, JsonWriter writer, ViewModelPropertyMap property, object value) { if (property.JsonConverter != null && property.JsonConverter.CanWrite && property.JsonConverter.CanConvert(property.Type)) { property.JsonConverter.WriteJson(writer, value, serializer); } else { serializer.Serialize(writer, value); } }
/// <summary> /// Gets the properties of the specified type. /// </summary> protected virtual IEnumerable<ViewModelPropertyMap> GetProperties(Type type) { foreach (var property in type.GetProperties(BindingFlags.Public | BindingFlags.Instance).OrderBy(p => p.Name)) { if (property.GetCustomAttribute<JsonIgnoreAttribute>() != null) continue; var propertyMap = new ViewModelPropertyMap() { PropertyInfo = property, Name = property.Name, ViewModelProtection = ProtectMode.None, Type = property.PropertyType, TransferAfterPostback = property.GetMethod != null && property.GetMethod.IsPublic, TransferFirstRequest = property.GetMethod != null && property.GetMethod.IsPublic, TransferToServer = property.SetMethod != null && property.SetMethod.IsPublic, JsonConverter = GetJsonConverter(property), Populate = ViewModelJsonConverter.IsComplexType(property.PropertyType) && !ViewModelJsonConverter.IsEnumerable(property.PropertyType) && property.GetMethod != null }; var bindAttribute = property.GetCustomAttribute<BindAttribute>(); if (bindAttribute != null) { propertyMap.TransferAfterPostback = bindAttribute.Direction.HasFlag(Direction.ServerToClientPostback); propertyMap.TransferFirstRequest = bindAttribute.Direction.HasFlag(Direction.ServerToClientFirstRequest); propertyMap.TransferToServer = bindAttribute.Direction.HasFlag(Direction.ClientToServerNotInPostbackPath) || bindAttribute.Direction.HasFlag(Direction.ClientToServerInPostbackPath); propertyMap.TransferToServerOnlyInPath = !bindAttribute.Direction.HasFlag(Direction.ClientToServerNotInPostbackPath) && propertyMap.TransferToServer; } var viewModelProtectionAttribute = property.GetCustomAttribute<ProtectAttribute>(); if (viewModelProtectionAttribute != null) { propertyMap.ViewModelProtection = viewModelProtectionAttribute.Settings; } var clientExtenderList = property.GetCustomAttributes<ClientExtenderAttribute>(); if (clientExtenderList.Any()) { clientExtenderList .OrderBy(c => c.Order) .ToList() .ForEach(extender => propertyMap.ClientExtenders.Add(new ClientExtenderInfo() { Name = extender.Name, Parameter = extender.Parameter })); } var validationAttributes = validationMetadataProvider.GetAttributesForProperty(property); propertyMap.ValidationRules = validationRuleTranslator.TranslateValidationRules(property, validationAttributes).ToList(); yield return propertyMap; } }
private static Expression GetSerializeExpression(ViewModelPropertyMap property, Expression jsonWriter, Expression value, Expression serializer) { if (property.JsonConverter?.CanWrite == true) { // maybe use the converter. It can't be easily inlined because polymorpism return(ExpressionUtils.Replace((JsonSerializer s, JsonWriter w, object v) => Serialize(s, w, property, v), serializer, jsonWriter, Expression.Convert(value, typeof(object)))); } else if (writeValueMethods.TryGetValue(value.Type, out var method)) { return(Expression.Call(jsonWriter, method, new [] { value })); } else { return(Expression.Call(serializer, "Serialize", Type.EmptyTypes, new [] { jsonWriter, Expression.Convert(value, typeof(object)) })); } }
private void AddTypeOptions(Dictionary <string, object> options, ViewModelPropertyMap property) { if (property.TransferToClient || property.TransferToServer) { if ((property.Type == typeof(DateTime) || property.Type == typeof(DateTime?)) && property.JsonConverter == null) // TODO: allow customization using attributes { options["isDate"] = true; } else if (property.Type.IsNumericType()) { options["type"] = property.Type.Name.ToLower(); } else if (Nullable.GetUnderlyingType(property.Type)?.IsNumericType() == true) { options["type"] = Nullable.GetUnderlyingType(property.Type).Name.ToLower() + "?"; } } }
private static object Deserialize(JsonSerializer serializer, JToken jtoken, ViewModelPropertyMap property, object existingValue) { if (property.JsonConverter != null && property.JsonConverter.CanRead && property.JsonConverter.CanConvert(property.Type)) { return property.JsonConverter.ReadJson(jtoken.CreateReader(), property.Type, existingValue, serializer); } else if (existingValue != null && property.Populate) { if (jtoken.Type == JTokenType.Null) return null; else if (jtoken.Type == JTokenType.Object) { serializer.Converters.OfType<ViewModelJsonConverter>().First().Populate((JObject)jtoken, serializer, existingValue); return existingValue; } else { serializer.Populate(jtoken.CreateReader(), existingValue); return existingValue; } } else { return serializer.Deserialize(jtoken.CreateReader(), property.Type); } }
public static void Ignore(this ViewModelPropertyMap property) { property.Bind(Direction.None); property.ValidationRules.Clear(); property.ClientExtenders.Clear(); }
public static ViewModelPropertyMap Protect(this ViewModelPropertyMap property, ProtectMode protectMode) { property.ViewModelProtection = protectMode; return(property); }
public static ViewModelPropertyMap AddClientExtender(this ViewModelPropertyMap property, ClientExtenderInfo clientExtender) { property.ClientExtenders.Add(clientExtender); return(property); }
public static ViewModelPropertyMap SetJsonConverter(this ViewModelPropertyMap property, JsonConverter converter) { property.JsonConverter = converter; return(property); }
public DotvvmPropertySerializationException(string message, Exception innerException, ViewModelPropertyMap serializedProperty) : base(message, innerException) { SerializedProperty = serializedProperty; }
private void GenerateOptionsBlock(IList<Expression> block, ViewModelPropertyMap property, Dictionary<string, object> options, ParameterExpression writer) { block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WritePropertyName(property.Name + "$options"), writer)); block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteStartObject(), writer)); foreach (var option in options) { block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WritePropertyName(option.Key), writer)); switch (option.Key) { case CLIENT_EXTENDERS_KEY: { // declare 'clientExtenders' as the array of objects block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteStartArray(), writer)); foreach (var extender in property.ClientExtenders) { block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteStartObject(), writer)); block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WritePropertyName("name"), writer)); block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteValue(extender.Name), writer)); block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WritePropertyName("parameter"), writer)); block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteValue(extender.Parameter), writer)); block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteEndObject(), writer)); } block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteEndArray(), writer)); break; } default: // legacy code - direct { property : value } block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteValue(option.Value), writer)); break; } } block.Add(ExpressionUtils.Replace<JsonWriter>(w => w.WriteEndObject(), writer)); }