public JsonNodeInfo VisitNode(JObject node, MappingContext mappingContext, NodeContext nodeContext) { var result = new JsonNodeInfo(); var idProp = node.Property("id"); var modelsProp = node.Property("models"); if (idProp != null && modelsProp != null) { node.Add("modelLinks", modelsProp.Value); modelsProp.Value = new JArray(); result.ServerTypeNameInfo = new TypeNameInfo("Make", ""); return result; } var makeProp = node.Property("make"); if (idProp != null && makeProp != null) { node.Add("makeLink", makeProp.Value); makeProp.Value = null; var catsProp = node.Property("categories"); if (catsProp != null) { var styleProps = catsProp["Vehicle Style"]; var styles = styleProps.Select(t => t.Value<String>()).ToAggregateString(", "); node.Add("vehicleStyles", new JValue(styles)); } result.ServerTypeNameInfo = new TypeNameInfo("Model", ""); return result; } return result; //// Model parser //else if (node.id && node.makeId) { // // move 'node.make' link so 'make' can be null reference // node.makeLink = node.make; // node.make = null; // // flatten styles and sizes as comma-separated strings // var styles = node.categories && node.categories["Vehicle Style"]; // node.vehicleStyles = styles && styles.join(", "); // var sizes = node.categories && node.categories["Vehicle Size"]; // node.vehicleSizes = sizes && sizes.join(", "); // return { entityType: "Model" }; //} }
public JsonNodeInfo VisitNode(NodeContext nodeContext) { return(JsonResultsAdapter.VisitNode(nodeContext.Node, this, nodeContext)); }
private void ParseObject(NodeContext nodeContext, EntityAspect targetAspect) { // backingStore will be null if not allowed to overwrite the entity. var backingStore = (targetAspect == null) ? null : targetAspect.BackingStore; var dict = (IDictionary <String, JToken>)nodeContext.Node; var structuralType = nodeContext.StructuralType; // needs to be the current namingConvention var nc = _mappingContext.EntityManager.MetadataStore.NamingConvention; dict.ForEach(kvp => { var key = nc.ServerPropertyNameToClient(kvp.Key, structuralType); var prop = structuralType.GetProperty(key); if (prop != null) { if (prop.IsDataProperty) { if (backingStore != null) { var dp = (DataProperty)prop; if (dp.IsComplexProperty) { var newCo = (IComplexObject)kvp.Value.ToObject(dp.ClrType); var co = (IComplexObject)backingStore[key]; var coBacking = co.ComplexAspect.BackingStore; newCo.ComplexAspect.BackingStore.ForEach(kvp2 => { coBacking[kvp2.Key] = kvp2.Value; }); } else { var val = kvp.Value; if (val.Type == JTokenType.Null && dp.ClrType != typeof(String) && !TypeFns.IsNullableType(dp.ClrType)) { // this can only happen if the client is nonnullable but the server is nullable. backingStore[key] = dp.DefaultValue; } else if (dp.IsEnumType || (dp.DataType.ClrType == typeof(TimeSpan))) { backingStore[key] = val.ToObject(dp.ClrType, _customSerializer); } else { backingStore[key] = val.ToObject(dp.ClrType); } } } } else { // prop is a ComplexObject var np = (NavigationProperty)prop; if (kvp.Value.HasValues) { NodeContext newContext; if (np.IsScalar) { var nestedOb = (JObject)kvp.Value; newContext = new NodeContext() { Node = nestedOb, ObjectType = prop.ClrType, StructuralProperty = np }; var entity = (IEntity)CreateAndPopulate(newContext); if (backingStore != null) { backingStore[key] = entity; } } else { var nestedArray = (JArray)kvp.Value; var navSet = (INavigationSet)TypeFns.CreateGenericInstance(typeof(NavigationSet <>), prop.ClrType); nestedArray.Cast <JObject>().ForEach(jo => { newContext = new NodeContext() { Node = jo, ObjectType = prop.ClrType, StructuralProperty = np }; var entity = (IEntity)CreateAndPopulate(newContext); navSet.Add(entity); }); // add to existing nav set if there is one otherwise just set it. object tmp; if (backingStore.TryGetValue(key, out tmp)) { var backingNavSet = (INavigationSet)tmp; navSet.Cast <IEntity>().ForEach(e => backingNavSet.Add(e)); } else { navSet.NavigationProperty = np; navSet.ParentEntity = targetAspect.Entity; backingStore[key] = navSet; } } } else { // do nothing //if (!np.IsScalar) { // return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType); //} else { // return null; //} } } } else { if (backingStore != null) { backingStore[key] = kvp.Value.ToObject <Object>(); } } }); }
protected virtual Object CreateAndPopulate(NodeContext nodeContext) { var node = nodeContext.Node; var nodeInfo = _mappingContext.VisitNode(nodeContext); if (nodeInfo.Ignore) { return(null); } node = nodeInfo.Node ?? node; if (nodeInfo.NodeRefId != null) { return(_mappingContext.RefMap[nodeInfo.NodeRefId]); } var metadataStore = _mappingContext.MetadataStore; EntityType entityType; Type objectType; if (nodeInfo.ServerTypeNameInfo != null) { var clientEntityTypeName = nodeInfo.ServerTypeNameInfo.ToClient(metadataStore).StructuralTypeName; entityType = metadataStore.GetEntityType(clientEntityTypeName); objectType = entityType.ClrType; if (!nodeContext.ObjectType.IsAssignableFrom(objectType)) { throw new Exception("Unable to convert returned type: " + objectType.Name + " into type: " + nodeContext.ObjectType.Name); } nodeContext.ObjectType = objectType; } else { objectType = nodeContext.ObjectType; entityType = metadataStore.GetEntityType(objectType); } // an entity type nodeContext.StructuralType = entityType; var keyValues = entityType.KeyProperties .Select(p => node[p.NameOnServer].ToObject(p.ClrType)) .ToArray(); var entityKey = EntityKey.Create(entityType, keyValues); var entity = _mappingContext.EntityManager.GetEntityByKey(entityKey); if (entity == null) { entity = (IEntity)Activator.CreateInstance(objectType); entity.EntityAspect.EntityType = entityType; } // must be called before populate if (nodeInfo.NodeId != null) { _mappingContext.RefMap[nodeInfo.NodeId] = entity; } _mappingContext.Entities.Add(entity); return(PopulateEntity(nodeContext, entity)); }
public JsonNodeInfo VisitNode(JObject node, MappingContext mappingContext, NodeContext nodeContext) { var result = new JsonNodeInfo(); JToken refToken; if (node.TryGetValue("$ref", out refToken)) { result.NodeRefId = refToken.Value<String>(); return result; } JToken idToken; if (node.TryGetValue("$id", out idToken)) { result.NodeId = idToken.Value<String>(); } JToken typeToken; if (node.TryGetValue("$type", out typeToken)) { var clrTypeName = typeToken.Value<String>(); result.ServerTypeNameInfo = TypeNameInfo.FromClrTypeName(clrTypeName); } return result; }
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.TokenType != JsonToken.Null) { // Load JObject from stream var node = JObject.Load(reader); var nodeContext = new NodeContext { Node = node, ObjectType = objectType }; // Create target object based on JObject var target = CreateAndPopulate( nodeContext); return target; } else { return null; } }
public JsonNodeInfo VisitNode(NodeContext nodeContext) { return JsonResultsAdapter.VisitNode(nodeContext.Node, this, nodeContext); }
private void ParseObject(NodeContext nodeContext, EntityAspect targetAspect) { // backingStore will be null if not allowed to overwrite the entity. var backingStore = (targetAspect == null) ? null : targetAspect.BackingStore; var dict = (IDictionary<String, JToken>) nodeContext.Node; var structuralType = nodeContext.StructuralType; // needs to be the current namingConvention var nc = _mappingContext.EntityManager.MetadataStore.NamingConvention; dict.ForEach(kvp => { var key = nc.ServerPropertyNameToClient(kvp.Key, structuralType); var prop = structuralType.GetProperty(key); if (prop != null) { if (prop.IsDataProperty) { if (backingStore != null) { var dp = (DataProperty)prop; if (dp.IsComplexProperty) { var newCo = (IComplexObject) kvp.Value.ToObject(dp.ClrType); var co = (IComplexObject)backingStore[key]; var coBacking = co.ComplexAspect.BackingStore; newCo.ComplexAspect.BackingStore.ForEach(kvp2 => { coBacking[kvp2.Key] = kvp2.Value; }); } else { var val = kvp.Value; if (val.Type == JTokenType.Null && dp.ClrType != typeof(String) && !TypeFns.IsNullableType(dp.ClrType)) { // this can only happen if the client is nonnullable but the server is nullable. backingStore[key] = dp.DefaultValue; } else if (dp.IsEnumType || (dp.DataType.ClrType == typeof (TimeSpan))) { backingStore[key] = val.ToObject(dp.ClrType, _customSerializer); } else { backingStore[key] = val.ToObject(dp.ClrType); } } } } else { // prop is a ComplexObject var np = (NavigationProperty)prop; if (kvp.Value.HasValues) { NodeContext newContext; if (np.IsScalar) { var nestedOb = (JObject)kvp.Value; newContext = new NodeContext() { Node = nestedOb, ObjectType = prop.ClrType, StructuralProperty = np}; var entity = (IEntity)CreateAndPopulate(newContext); if (backingStore != null) backingStore[key] = entity; } else { var nestedArray = (JArray)kvp.Value; var navSet = (INavigationSet) TypeFns.CreateGenericInstance(typeof(NavigationSet<>), prop.ClrType); nestedArray.Cast<JObject>().ForEach(jo => { newContext = new NodeContext() { Node=jo, ObjectType = prop.ClrType, StructuralProperty = np}; var entity = (IEntity)CreateAndPopulate(newContext); navSet.Add(entity); }); // add to existing nav set if there is one otherwise just set it. object tmp; if (backingStore.TryGetValue(key, out tmp)) { var backingNavSet = (INavigationSet) tmp; navSet.Cast<IEntity>().ForEach(e => backingNavSet.Add(e)); } else { navSet.NavigationProperty = np; navSet.ParentEntity = targetAspect.Entity; backingStore[key] = navSet; } } } else { // do nothing //if (!np.IsScalar) { // return TypeFns.ConstructGenericInstance(typeof(NavigationSet<>), prop.ClrType); //} else { // return null; //} } } } else { if (backingStore != null) backingStore[key] = kvp.Value.ToObject<Object>(); } }); }
protected virtual Object PopulateEntity(NodeContext nodeContext, IEntity entity) { var aspect = entity.EntityAspect; if (aspect.EntityManager == null) { // new to this entityManager ParseObject(nodeContext, aspect); aspect.Initialize(); // TODO: This is a nit. Wierd case where a save adds a new entity will show up with // a AttachOnQuery operation instead of AttachOnSave _mappingContext.EntityManager.AttachQueriedEntity(entity, (EntityType) nodeContext.StructuralType); } else if (_mappingContext.MergeStrategy == MergeStrategy.OverwriteChanges || aspect.EntityState == EntityState.Unchanged) { // overwrite existing entityManager ParseObject(nodeContext, aspect); aspect.Initialize(); aspect.OnEntityChanged(_mappingContext.LoadingOperation == LoadingOperation.Query ? EntityAction.MergeOnQuery : EntityAction.MergeOnSave); } else { // preserveChanges handling - we still want to handle expands. ParseObject(nodeContext, null ); } return entity; }
protected virtual Object CreateAndPopulate(NodeContext nodeContext) { var node = nodeContext.Node; var nodeInfo = _mappingContext.VisitNode(nodeContext); if (nodeInfo.Ignore) return null; node = nodeInfo.Node ?? node; if (nodeInfo.NodeRefId != null) { return _mappingContext.RefMap[nodeInfo.NodeRefId]; } var metadataStore = _mappingContext.MetadataStore; EntityType entityType; Type objectType; if (nodeInfo.ServerTypeNameInfo != null) { var clientEntityTypeName = nodeInfo.ServerTypeNameInfo.ToClient(metadataStore).StructuralTypeName; entityType = metadataStore.GetEntityType(clientEntityTypeName); objectType = entityType.ClrType; if (!nodeContext.ObjectType.IsAssignableFrom(objectType)) { throw new Exception("Unable to convert returned type: " + objectType.Name + " into type: " + nodeContext.ObjectType.Name); } nodeContext.ObjectType = objectType; } else { objectType = nodeContext.ObjectType; entityType = metadataStore.GetEntityType(objectType); } // an entity type nodeContext.StructuralType = entityType; var keyValues = entityType.KeyProperties .Select(p => node[p.NameOnServer].ToObject(p.ClrType)) .ToArray(); var entityKey = EntityKey.Create(entityType, keyValues); var entity = _mappingContext.EntityManager.GetEntityByKey(entityKey); if (entity == null) { entity = (IEntity) Activator.CreateInstance(objectType); entity.EntityAspect.EntityType = entityType; } // must be called before populate if (nodeInfo.NodeId != null) { _mappingContext.RefMap[nodeInfo.NodeId] = entity; } _mappingContext.Entities.Add(entity); return PopulateEntity(nodeContext, entity); }