/// <summary> /// Default constructor /// </summary> /// <param name="mode">Mapping mode</param> /// <param name="jsonProperty">Json property name</param> /// <param name="entityProperty">Entity property</param> /// <param name="mapToJsonAction">Delegate to set entity property to json object</param> /// <param name="mapToEntityAction">Delagate to set json property to entity object</param> public JsonMapperEntry(JsonMapperEntryMode mode, string jsonProperty, PropertyInfo entityProperty, Action <T, JObject> mapToJsonAction, Action <JObject, T> mapToEntityAction) { Mode = mode; JsonProperty = jsonProperty; EntityProperty = entityProperty; _mapToJsonAction = mapToJsonAction; _mapToEntityAction = mapToEntityAction; }
public void AdjustParameters(List<MetadataParameter> parameters, XElement adjustElement, JsonMapperEntryMode? jsonMode = null) { foreach (var parameterElement in adjustElement.Elements("parameter") .Where(p => p.Attribute("name") != null)) { var name = (string)parameterElement.Attribute("name"); var type = (string)parameterElement.Attribute("type"); var mode = (string)parameterElement.Attribute("mode"); var required = (bool?)parameterElement.Attribute("required"); var after = (string)parameterElement.Attribute("after"); // remove an existing parameter if (mode == "remove") { parameters.RemoveAll(p => p.Name.StartsWith(name)); continue; } // add or update an existing parameter var param = parameters.FirstOrDefault(p => p.Name == name); if (param == null) { param = new MetadataParameter { Name = name, Type = type }; var index = parameters.Count; if (after != null) { var target = parameters.FirstOrDefault(p => p.Name == after); if (target != null) index = parameters.IndexOf(target) + 1; } parameters.Insert(index, param); } if (!string.IsNullOrEmpty(parameterElement.Contents())) { param.Documentation = parameterElement.Contents(); } if (required != null) { param.IsRequred = required.Value; } // if element includes cref - parse the specified type and add parameters from it var cref = GetCrefType(parameterElement); if (cref != null) { if (param.Type == null) param.Type = "object"; var paramJsonMode = jsonMode; if (paramJsonMode != null && mode == "OneWayOnly") paramJsonMode = paramJsonMode.Value | JsonMapperEntryMode.OneWayOnly; parameters.AddRange(GetTypeParameters(cref, paramJsonMode, param.Name + (type == "array" ? "[]" : null) + ".")); } } }
/// <summary> /// Default constructor /// </summary> /// <param name="mode">Mapping mode</param> /// <param name="jsonProperty">Json property name</param> /// <param name="entityProperty">Entity property</param> /// <param name="mapToJsonAction">Delegate to set entity property to json object</param> /// <param name="mapToEntityAction">Delagate to set json property to entity object</param> public JsonMapperEntry(JsonMapperEntryMode mode, string jsonProperty, PropertyInfo entityProperty, Action <T, JObject> mapToJsonAction, Action <JObject, T, bool> mapToEntityAction) { Mode = mode; JsonProperty = jsonProperty; EntityProperty = entityProperty; if ((Mode & JsonMapperEntryMode.TwoWay) != JsonMapperEntryMode.TwoWay) { Mode |= JsonMapperEntryMode.OneWayOnly; } _mapToJsonAction = mapToJsonAction; _mapToEntityAction = mapToEntityAction; }
public MetadataParameter[] GetTypeParameters(Type type, JsonMapperEntryMode? mode = null, string prefix = null) { // get JSON mapping manager var mapper = _jsonMapperManager.GetMapper(type); if (mapper == null) return new MetadataParameter[] { }; // create parameters from mapping entries var parameters = new List<MetadataParameter>(); foreach (var parameter in mapper.Entries.Where(e => mode == null || (mode.Value & e.Mode) == mode.Value)) { // add parameter that corresponds to the mapped property var propertyType = parameter.EntityProperty.PropertyType; var isJsonObject = parameter.EntityProperty.IsDefined(typeof(JsonFieldAttribute), false); var param = new MetadataParameter { Name = prefix + parameter.JsonProperty, Type = isJsonObject ? "object" : ToJsonType(propertyType), IsRequred = IsRequired(parameter.EntityProperty), Documentation = _xmlCommentReader.GetPropertyElement(parameter.EntityProperty).ElementContents("summary"), }; parameters.Add(param); // add child object parameters if (param.Type == "object" && !isJsonObject) { parameters.AddRange(GetTypeParameters(propertyType, mode, param.Name + ".")); } else if (param.Type == "array") { var elementType = propertyType.GetInterfaces().First(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)).GetGenericArguments().First(); if (ToJsonType(elementType) == "object") { parameters.AddRange(GetTypeParameters(elementType, mode, param.Name + "[].")); } } } return parameters.ToArray(); }
/// <summary> /// Configures property mapping /// </summary> /// <param name="entityPropertyExpression">Property access expression</param> /// <param name="jsonProperty">Json property name</param> /// <param name="mode">Mapping mode</param> /// <returns>Current configuration object</returns> public JsonMapperConfiguration <T> Property(Expression <Func <T, object> > entityPropertyExpression, string jsonProperty, JsonMapperEntryMode mode = JsonMapperEntryMode.TwoWay) { if (entityPropertyExpression == null) { throw new ArgumentNullException("entityPropertyExpression"); } if (string.IsNullOrEmpty(jsonProperty)) { throw new ArgumentException("jsonProperty is null or empty!", "jsonProperty"); } var entity = Expression.Parameter(typeof(T), "entity"); var json = Expression.Parameter(typeof(JObject), "json"); var entityProperty = GetProperty(entityPropertyExpression); // create MapToJson action var jsonAddProperty = Expression.Call(json, typeof(JObject).GetMethod("Add", new[] { typeof(JProperty) }), Expression.New(typeof(JProperty).GetConstructor(new[] { typeof(string), typeof(object) }), Expression.Constant(jsonProperty), Expression.Invoke(entityPropertyExpression, entity))); var mapToJsonLabmda = Expression.Lambda <Action <T, JObject> >(jsonAddProperty, entity, json); // create MapToEntity action var jsonPropertyCall = Expression.Call(json, typeof(JObject).GetMethod("Property"), Expression.Constant(jsonProperty)); var entityAssign = Expression.IfThen( Expression.NotEqual(jsonPropertyCall, Expression.Constant(null, typeof(JProperty))), Expression.Assign( Expression.Property(entity, entityProperty), Expression.Convert(Expression.Property(jsonPropertyCall, "Value"), entityProperty.PropertyType))); var mapToEntityLabmda = Expression.Lambda <Action <JObject, T> >(entityAssign, json, entity); Entries.Add(new JsonMapperEntry <T>(mode, jsonProperty, entityProperty, mapToJsonLabmda.Compile(), mapToEntityLabmda.Compile())); return(this); }
/// <summary> /// Configures reference property /// </summary> /// <typeparam name="TRef">Reference object type</typeparam> /// <param name="entityPropertyExpression">Property access expression</param> /// <param name="jsonProperty">Json property name</param> /// <param name="mode">Mapping mode</param> /// <returns>Current configuration object</returns> public JsonMapperConfiguration <T> ReferenceProperty <TRef>(Expression <Func <T, TRef> > entityPropertyExpression, string jsonProperty, JsonMapperEntryMode mode = JsonMapperEntryMode.TwoWay) { if (entityPropertyExpression == null) { throw new ArgumentNullException("entityPropertyExpression"); } if (string.IsNullOrEmpty(jsonProperty)) { throw new ArgumentException("jsonProperty is null or empty!", "jsonProperty"); } var entity = Expression.Parameter(typeof(T), "entity"); var json = Expression.Parameter(typeof(JObject), "json"); var entityProperty = GetProperty(entityPropertyExpression); var mapper = _manager.GetMapper <TRef>(); var repository = _dataContext.GetRepositoryFor <TRef>(); // create MapToJson action var jsonAddProperty = Expression.Call(json, typeof(JObject).GetMethod("Add", new[] { typeof(JProperty) }), Expression.New(typeof(JProperty).GetConstructor(new[] { typeof(string), typeof(object) }), Expression.Constant(jsonProperty), Expression.Condition( Expression.NotEqual(Expression.Invoke(entityPropertyExpression, entity), Expression.Constant(null, typeof(TRef))), Expression.Call(Expression.Constant(mapper), typeof(IJsonMapper <>).MakeGenericType(typeof(TRef)) .GetMethod("Map", new[] { typeof(TRef) }), Expression.Invoke(entityPropertyExpression, entity)), Expression.Constant(null, typeof(JObject))))); var mapToJsonLabmda = Expression.Lambda <Action <T, JObject> >(jsonAddProperty, entity, json); // create MapToEntity action - use delegate for simplicity Action <JObject, T> mapToEntityLabmda = (json2, entity2) => { var jProperty = json2.Property(jsonProperty); if (jProperty == null) { return; } TRef refValue = default(TRef); var jValue = jProperty.Value as JValue; if (jValue != null && jValue.Type == JTokenType.Null) { // null is passed - have to reset the foreign key property as well var fkProperty = typeof(T).GetProperty(entityProperty.Name + "ID"); if (fkProperty != null) { fkProperty.SetValue(entity2, null, null); } } else if (jValue != null && (jValue.Value is long)) { // search object by ID refValue = repository.Get((int)jValue); if (refValue == null) { throw new JsonMapperException(string.Format("ID of the reference property is not found! " + "Property: {0}, ID: {1}", jsonProperty, jValue)); } } else { throw new JsonMapperException(string.Format("The required reference property has invalid format! " + "Property: {0}", jsonProperty)); } entityProperty.SetValue(entity2, refValue, null); }; Entries.Add(new JsonMapperEntry <T>(mode, jsonProperty, entityProperty, mapToJsonLabmda.Compile(), mapToEntityLabmda)); return(this); }
private MetadataParameter[] GetTypeParameters(Type type, JsonMapperEntryMode? exclude = null, string prefix = null) { // get JSON mapping manager var mapper = JsonMapperManager.GetMapper(type); if (mapper == null) return new MetadataParameter[] { }; // create parameters from mapping entries var parameters = new List<MetadataParameter>(); foreach (var parameter in mapper.Entries.Where(e => exclude == null || e.Mode != exclude.Value)) { // add parameter that corresponds to the mapped property var isJsonObject = parameter.EntityProperty.IsDefined(typeof(JsonFieldAttribute), false); var param = new MetadataParameter { Name = (prefix == null ? null : prefix + ".") + parameter.JsonProperty, Type = isJsonObject ? "object" : ToJsonType(parameter.EntityProperty.PropertyType), IsRequred = IsRequired(parameter.EntityProperty), Documentation = DataXmlCommentReader.GetPropertyElement(parameter.EntityProperty).ElementContents("summary"), }; parameters.Add(param); // add child object parameters if (param.Type == "object" && !isJsonObject) { parameters.AddRange(GetTypeParameters(parameter.EntityProperty.PropertyType, exclude, param.Name)); } } return parameters.ToArray(); }
/// <summary> /// Configures property mapping /// </summary> /// <param name="entityPropertyExpression">Property access expression</param> /// <param name="jsonProperty">Json property name</param> /// <param name="mode">Mapping mode</param> /// <returns>Current configuration object</returns> public JsonMapperConfiguration <T> Property(Expression <Func <T, object> > entityPropertyExpression, string jsonProperty, JsonMapperEntryMode mode = JsonMapperEntryMode.TwoWay) { if (entityPropertyExpression == null) { throw new ArgumentNullException("entityPropertyExpression"); } if (string.IsNullOrEmpty(jsonProperty)) { throw new ArgumentException("jsonProperty is null or empty!", "jsonProperty"); } var entityProperty = GetProperty(entityPropertyExpression); // create MapToJson action var entityPropertyLambda = entityPropertyExpression.Compile(); var entityConversionLambda = GetValueFormatter(entityProperty.PropertyType); Action <T, JObject> mapToJsonLabmda = (entity, json) => { var value = entityPropertyLambda(entity); json.Add(new JProperty(jsonProperty, entityConversionLambda(value))); }; // create MapToEntity action var entityPropertySetterLambda = GetPropertySetter(entityProperty); var jsonTokenParser = GetJsonTokenParser(entityProperty); Action <JObject, T, bool> mapToEntityLabmda = (json, entity, patch) => { var jProperty = json.Property(jsonProperty); if (jProperty != null || !patch) { var value = jsonTokenParser(jsonProperty, jProperty != null ? jProperty.Value : null); entityPropertySetterLambda(entity, value); } }; Entries.Add(new JsonMapperEntry <T>(mode, jsonProperty, entityProperty, mapToJsonLabmda, mapToEntityLabmda)); return(this); }
/// <summary> /// Configures collection property /// </summary> /// <param name="entityPropertyExpression">Property access expression</param> /// <param name="jsonProperty">Json property name</param> /// <param name="mode">Mapping mode</param> /// <returns>Current configuration object</returns> public JsonMapperConfiguration <T> CollectionProperty <TRef>(Expression <Func <T, IList <TRef> > > entityPropertyExpression, string jsonProperty, JsonMapperEntryMode mode = JsonMapperEntryMode.TwoWay) { if (entityPropertyExpression == null) { throw new ArgumentNullException("entityPropertyExpression"); } if (string.IsNullOrEmpty(jsonProperty)) { throw new ArgumentException("jsonProperty is null or empty!", "jsonProperty"); } var entityProperty = GetProperty(entityPropertyExpression); var mapper = _manager.GetMapper <TRef>(); // create MapToJson action var entityPropertyLambda = entityPropertyExpression.Compile(); Action <T, JObject> mapToJsonLabmda = (entity, json) => { var value = entityPropertyLambda(entity); json.Add(new JProperty(jsonProperty, value == null ? null : value.Select(item => mapper.Map(item)).ToArray())); }; // create MapToEntity action var entityPropertySetterLambda = GetPropertySetter(entityProperty); Action <JObject, T, bool> mapToEntityLabmda = (json, entity, patch) => { var jProperty = json.Property(jsonProperty); if (jProperty != null || !patch) { var refValue = (IList <TRef>)null; if (jProperty != null && jProperty.Value.Type == JTokenType.Array) { refValue = (IList <TRef>)Activator.CreateInstance(entityProperty.PropertyType); foreach (var element in (JArray)jProperty.Value) { if (element.Type != JTokenType.Object) { throw new JsonMapperException("The element of the collection property has invalid format, property: " + jsonProperty); } refValue.Add(mapper.Map((JObject)element)); } } else if (jProperty != null && jProperty.Value.Type != JTokenType.Null) { throw new JsonMapperException("The value of the collection property has invalid format, property: " + jsonProperty); } entityPropertySetterLambda(entity, refValue); } }; Entries.Add(new JsonMapperEntry <T>(mode, jsonProperty, entityProperty, mapToJsonLabmda, mapToEntityLabmda)); return(this); }
/// <summary> /// Configures reference property /// </summary> /// <typeparam name="TRef">Reference object type</typeparam> /// <param name="entityPropertyExpression">Property access expression</param> /// <param name="jsonProperty">Json property name</param> /// <param name="mode">Mapping mode</param> /// <returns>Current configuration object</returns> public JsonMapperConfiguration <T> ReferenceProperty <TRef>(Expression <Func <T, TRef> > entityPropertyExpression, string jsonProperty, JsonMapperEntryMode mode = JsonMapperEntryMode.TwoWay) { if (entityPropertyExpression == null) { throw new ArgumentNullException("entityPropertyExpression"); } if (string.IsNullOrEmpty(jsonProperty)) { throw new ArgumentException("jsonProperty is null or empty!", "jsonProperty"); } var entityProperty = GetProperty(entityPropertyExpression); var mapper = _manager.GetMapper <TRef>(); // create MapToJson action var entityPropertyLambda = entityPropertyExpression.Compile(); Action <T, JObject> mapToJsonLabmda = (entity, json) => { var value = entityPropertyLambda(entity); json.Add(new JProperty(jsonProperty, value == null ? null : mapper.Map(value))); }; // create MapToEntity action var entityPropertySetterLambda = GetPropertySetter(entityProperty); Action <JObject, T, bool> mapToEntityLabmda = (json, entity, patch) => { var jProperty = json.Property(jsonProperty); if (jProperty != null || !patch) { TRef refValue = default(TRef); if (jProperty == null || jProperty.Value.Type == JTokenType.Null) { // null is passed - have to reset the foreign key property as well var fkProperty = typeof(T).GetProperty(entityProperty.Name + "ID"); if (fkProperty != null) { fkProperty.SetValue(entity, null, null); } } else if (jProperty.Value.Type == JTokenType.Object) { // apply the reference object refValue = entityPropertyLambda(entity); if (refValue == null || !patch) { refValue = (TRef)Activator.CreateInstance(typeof(TRef)); } mapper.Apply(refValue, (JObject)jProperty.Value, patch); } else { throw new JsonMapperException("The value of the object property has invalid format, property: " + jsonProperty); } entityPropertySetterLambda(entity, refValue); } }; Entries.Add(new JsonMapperEntry <T>(mode, jsonProperty, entityProperty, mapToJsonLabmda, mapToEntityLabmda)); return(this); }
/// <summary> /// Configures property mapping /// </summary> /// <param name="entityPropertyExpression">Property access expression</param> /// <param name="jsonProperty">Json property name</param> /// <param name="mode">Mapping mode</param> /// <returns>Current configuration object</returns> public JsonMapperConfiguration <T> EnumProperty <TEnum>(Expression <Func <T, int?> > entityPropertyExpression, string jsonProperty, JsonMapperEntryMode mode = JsonMapperEntryMode.TwoWay) where TEnum : struct { if (entityPropertyExpression == null) { throw new ArgumentNullException("entityPropertyExpression"); } if (string.IsNullOrEmpty(jsonProperty)) { throw new ArgumentException("jsonProperty is null or empty!", "jsonProperty"); } if (!typeof(TEnum).IsEnum) { throw new ArgumentException("TEnum is not an enum type!", "TEnum"); } var entityProperty = GetProperty(entityPropertyExpression); var isNullable = Nullable.GetUnderlyingType(entityProperty.PropertyType) != null; // create MapToJson action var entityPropertyLambda = entityPropertyExpression.Compile(); var entityConversionLambda = GetValueFormatter(typeof(TEnum)); Action <T, JObject> mapToJsonLabmda = (entity, json) => { var value = Enum.ToObject(typeof(TEnum), entityPropertyLambda(entity)); json.Add(new JProperty(jsonProperty, entityConversionLambda(value).ToString())); }; // create MapToEntity action var entityPropertySetterLambda = GetPropertySetter(entityProperty); var jsonTokenParser = GetJsonTokenParser(entityProperty, isNullable ? typeof(Nullable <TEnum>) : typeof(TEnum)); Action <JObject, T, bool> mapToEntityLabmda = (json, entity, patch) => { var jProperty = json.Property(jsonProperty); if (jProperty != null || !patch) { var value = jsonTokenParser(jsonProperty, jProperty != null ? jProperty.Value : null); entityPropertySetterLambda(entity, value); } }; Entries.Add(new JsonMapperEntry <T>(mode, jsonProperty, entityProperty, mapToJsonLabmda, mapToEntityLabmda)); return(this); }