private static Expression <ObjectConstructor <object> > CreateFactory(Type type, JsonPropertyCollection properties, List <Func <ModelObjectSerializationContext, object> > injectors, ParameterExpression context) { var arrayArg = Expression.Parameter(typeof(object[])); var constructor = type.GetConstructor(properties.Select(p => p.PropertyType).ToArray()); var arguments = properties.Select(CreateArgumentExpression); return(Expression.Lambda <ObjectConstructor <object> >( Expression.New(constructor, arguments), arrayArg)); UnaryExpression CreateArgumentExpression(JsonProperty property, int i) => Expression.Convert( injectors[i] != null ? (Expression)Expression.Invoke(Expression.Constant(injectors[i]), context) : Expression.ArrayIndex(arrayArg, Expression.Constant(i)), property.PropertyType); }
internal static bool ResolveEntityProperties(IList <JsonProperty> jsonProperties, Type entityType, EntityTypeInfo entityTypeInfo, EntityService entityService, DefaultContractResolver resolver, Func <PropertyInfo, JsonProperty> createPropertyFunc) { if (entityService.ContainsEntityType(entityType)) { if (jsonProperties.Any(jp => jp.PropertyName == Defaults.MetadataPropertyName && jp.UnderlyingName == Defaults.DummyMetadataPropertyInfo.Name)) { return(false); //if we ever find the metadata property there, assume it has been resolved. } var _properties = new JsonPropertyCollection(entityType); var isComplex = entityType.IsComplex(); var propertiesToIgnore = entityTypeInfo.PropertiesToIgnore.ToArray(); foreach (var jsonProp in jsonProperties) { if (isComplex) { jsonProp.NullValueHandling = NullValueHandling.Include; //we need null values for complex types jsonProp.DefaultValueHandling = DefaultValueHandling.Include; //we need all properties serialized } if (!jsonProp.Ignored && propertiesToIgnore.Any(np => np.Name == jsonProp.UnderlyingName)) { jsonProp.Ignored = true; } _properties.Add(jsonProp); } lock (entityTypeInfo) { //check for complextypes var complexTypedProperties = entityTypeInfo.ComplexTypedProperties; var complexJsonProperties = new List <JsonProperty>(); if (complexTypedProperties?.Count > 0) { //filter to complexproperties var filteredJsonProperties = _properties? .Select(p => new { JsonProperty = p, PropertyInfo = complexTypedProperties.Where(pi => pi.Name == p.UnderlyingName) .FirstOrDefault() }) .Where(np => np.PropertyInfo != null) .ToDictionary(np => np.JsonProperty, np => np.PropertyInfo); Func <Type, IList <JsonProperty> > getResolvedPropertiesFunc = t => { var contract = resolver.ResolveContract(t) as JsonObjectContract; if (contract.Properties?.Count > 0) { ResolveEntityProperties (contract.Properties, t, entityService.GetEntityTypeInfo(t), entityService, resolver, createPropertyFunc); } return(contract.Properties); }; //generate new properties with new names for the complex types foreach (var complexTypedJsonProp in filteredJsonProperties) { //get the complexTypedProperty's own jsonproperties //include derived classes var derivedTypes = entityService .GetDerivedEntityTypes(complexTypedJsonProp.Key.PropertyType)? .Where(t => t.IsComplex()).ToList(); if (derivedTypes == null || derivedTypes.Count == 0) { entityService.AddEntityType(complexTypedJsonProp.Key.PropertyType); derivedTypes = new List <Type> { complexTypedJsonProp.Key.PropertyType }; } var childProperties = derivedTypes .SelectMany(dt => getResolvedPropertiesFunc(dt)?.Where (p => /*!p.Ignored &&*/ p.PropertyName != Defaults.MetadataPropertyName) ?? new JsonProperty[0], (dt, property) => new { DerivedType = dt, Property = property }) .Where(jp => jp.Property != null) .GroupBy(jp => jp.Property.PropertyName) .Select(jpg => jpg.FirstOrDefault()) .ToList(); foreach (var childProp in childProperties) { //add the child to this type's properties try { var newChildProp = GetComplexTypedPropertyChild (childProp.DerivedType, complexTypedJsonProp.Key, complexTypedJsonProp.Value, childProp.Property); _properties.AddProperty(newChildProp); complexJsonProperties.Add(newChildProp); } catch (JsonSerializationException e) { //for some reason member already exists and is duplicate } } //ignore all complex typed properties complexTypedJsonProp.Key.Ignored = true; } } var nextIdx = -1; //clear and re-add these properties jsonProperties.Clear(); var orderedProperties = _properties.OrderBy(p => p.Order ?? nextIdx++); foreach (var prop in orderedProperties) { jsonProperties.Add(prop); } //create metadata property and add it last var metadataJsonProperty = createPropertyFunc(Defaults.DummyMetadataPropertyInfo); metadataJsonProperty.PropertyName = Defaults.MetadataPropertyName; metadataJsonProperty.ValueProvider = new MetadataValueProvider(entityType, complexJsonProperties); metadataJsonProperty.ShouldSerialize = instance => { return(!(metadataJsonProperty.ValueProvider as MetadataValueProvider) .BuildMetadata(instance).IsEmpty()); }; metadataJsonProperty.Order = int.MaxValue; //try to make it the last serialized jsonProperties.Add(metadataJsonProperty); //assign and resolve these properties entityTypeInfo.JsonProperties = new List <JsonProperty>(jsonProperties); return(true); } } return(false); }