Exemplo n.º 1
0
        /// <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);
        }