Beispiel #1
0
        /// <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();
        }
Beispiel #8
0
        /// <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);
        }
Beispiel #9
0
        /// <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);
        }
Beispiel #10
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);
        }
Beispiel #11
0
        /// <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);
        }