private DataProperty CreateDataProperty(StructuralType structuralType, PropertyInfo pInfo) { var propType = pInfo.PropertyType; var dp = new DataProperty(pInfo.Name); // TODO: handle isScalar if (typeof(IComplexObject).IsAssignableFrom(propType)) { dp.ComplexType = MetadataStore.GetComplexType(propType); dp.IsNullable = false; // complex Objects do not have defaultValues currently } else { var nnType = TypeFns.GetNonNullableType(propType); dp.ClrType = propType; dp.DataType = DataType.FromClrType(nnType); dp.IsNullable = TypeFns.IsNullableType(propType); dp.DefaultValue = dp.IsNullable ? null : dp.DataType.DefaultValue; var isEnumType = nnType.GetTypeInfo().IsEnum; if (isEnumType) { dp.EnumTypeName = nnType.FullName; } } structuralType.AddDataProperty(dp); return(dp); }
private Expression GetPropertyExpression(Expression expr, string propertyName, Type returnType) { if (TypeFns.IsNullableType(expr.Type)) { var nullBaseExpression = Expression.Constant(null, expr.Type); var test = Expression.Equal(expr, nullBaseExpression); expr = Expression.Convert(expr, TypeFns.GetNonNullableType(expr.Type)); Expression propExpr = Expression.PropertyOrField(expr, propertyName); propExpr = Expression.Convert(propExpr, TypeFns.GetNullableType(returnType)); var nullExpr = Expression.Constant(null, TypeFns.GetNullableType(returnType)); return(Expression.Condition(test, nullExpr, propExpr)); } else { return(Expression.PropertyOrField(expr, propertyName)); } }
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>(); } } }); }
private Expression BuildBinaryExpr(Expression expr1, Expression expr2, Operator op) { if (expr1.Type != expr2.Type) { if (TypeFns.IsNullableType(expr1.Type) && !TypeFns.IsNullableType(expr2.Type)) { expr2 = Expression.Convert(expr2, expr1.Type); } else if (TypeFns.IsNullableType(expr2.Type) && !TypeFns.IsNullableType(expr1.Type)) { expr1 = Expression.Convert(expr1, expr2.Type); } if (HasNullValue(expr2) && CannotBeNull(expr1)) { expr1 = Expression.Convert(expr1, TypeFns.GetNullableType(expr1.Type)); } else if (HasNullValue(expr1) && CannotBeNull(expr2)) { expr2 = Expression.Convert(expr2, TypeFns.GetNullableType(expr2.Type)); } } if (op == BinaryOperator.Equals) { return(Expression.Equal(expr1, expr2)); } else if (op == BinaryOperator.NotEquals) { return(Expression.NotEqual(expr1, expr2)); } else if (op == BinaryOperator.GreaterThan) { return(Expression.GreaterThan(expr1, expr2)); } else if (op == BinaryOperator.GreaterThanOrEqual) { return(Expression.GreaterThanOrEqual(expr1, expr2)); } else if (op == BinaryOperator.LessThan) { return(Expression.LessThan(expr1, expr2)); } else if (op == BinaryOperator.LessThanOrEqual) { return(Expression.LessThanOrEqual(expr1, expr2)); } else if (op == BinaryOperator.StartsWith) { var mi = TypeFns.GetMethodByExample((String s) => s.StartsWith("abc")); return(Expression.Call(expr1, mi, expr2)); } else if (op == BinaryOperator.EndsWith) { var mi = TypeFns.GetMethodByExample((String s) => s.EndsWith("abc")); return(Expression.Call(expr1, mi, expr2)); } else if (op == BinaryOperator.Contains) { var mi = TypeFns.GetMethodByExample((String s) => s.Contains("abc")); return(Expression.Call(expr1, mi, expr2)); } else if (op == BinaryOperator.In) { // TODO: need to generalize this past just 'string' var mi = TypeFns.GetMethodByExample((List <String> list) => list.Contains("abc"), expr1.Type); return(Expression.Call(expr2, mi, expr1)); } return(null); }