/// <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 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); }