public static TPOCO CreatePOCO <T, TPOCO>(this T source) where T : IModelEntity where TPOCO : IPOCO <T>, new() { Func <bool, object, bool, IPOCOContainer> getReferenceValue = (isEnumerable, propVal, isLoaded) => isEnumerable ? (IPOCOContainer) new POCOCollection(propVal as IEnumerable, isLoaded) : (IPOCOContainer) new POCOReference(propVal, isLoaded); TPOCO poco = new TPOCO(); foreach (var prop in typeof(TPOCO).GetProperties()) { var propOnSource = typeof(T).GetProperty(prop.Name); if (typeof(IPOCOContainer).IsAssignableFrom(prop.PropertyType)) { prop.SetValue(poco, getReferenceValue(TypesUtil.IsNonPrimitiveCollection(propOnSource.PropertyType), propOnSource.GetValue(source), source._getIntermediateEntity().IsLoaded(makeFieldSelector <T>(propOnSource)))); } else { prop.SetValue(poco, propOnSource.GetValue(source)); } } return(poco); }
//Fills an Enumerable (List, Collection etc) with items private object FillEnumerable(object enumerable, List <object> items) { var enumerableType = enumerable.GetType(); if (enumerableType.IsArray) //Array { for (int i = 0; i < items.Count; i++) { (enumerable as Array).SetValue(items[i], i); } } else if (typeof(IList).IsAssignableFrom(enumerableType)) //List and derived types .. which have indexers { for (int i = 0; i < items.Count; i++) { (enumerable as IList)[i] = items[i]; } } else if (enumerableType.IsGenericType && TypesUtil.IsNonPrimitiveCollection(enumerableType)) //Custom generic collections { enumerableType.GetMethod("Clear").Invoke(enumerable, null); var addMethod = enumerableType.GetMethod("Add"); foreach (var item in items) { addMethod.Invoke(enumerable, new object[] { item }); } } else { throw new NotSupportedException("The collection of type " + enumerableType.ToString() + " cannot be bound to the context."); } return(enumerable); }
public static object GetCollectionInstance(Type collectionType, List <object> collection) { //Arrays if (collectionType.IsArray) { var array = Activator.CreateInstance(collectionType, collection.Count) as Array; for (int i = 0; i < collection.Count; i++) { array.SetValue(collection[i], i); } return(array); } //lists with indexers else if (collectionType.IsGenericType && collectionType.IsInterface && TypesUtil.IsNonPrimitiveCollection(collectionType)) { var list = Activator.CreateInstance(typeof(List <>) .MakeGenericType(TypesUtil.GetGenericArgumentForBaseType(collectionType, typeof(ICollection <>)))) as IList; collection.ForEach(item => list.Add(item)); return(list); } //Custom generic collections .. assume they have default constructor and Add method else if (collectionType.IsGenericType && TypesUtil.IsNonPrimitiveCollection(collectionType) && collectionType.GetConstructor(Type.EmptyTypes) != null) { var customCollection = Activator.CreateInstance(collectionType); var addMethod = collectionType.GetMethod("Add"); collection.ForEach(item => addMethod.Invoke(customCollection, new object[] { item })); return(customCollection); } throw new NotSupportedException("Only Arrays, Lists, ICollection<> and Custom collection types with default constructor are supported."); }
private List <IUnprojectedBinding> GetUnprojectedBindings(IEnumerable <IRequestedBinding> requestedBindings) { var result = new List <IUnprojectedBinding>(); foreach (var target in requestedBindings.Where(b => TypesUtil.IsNonPrimitiveCollection(b.Type))) { if (target is UnprojectedIncludeInCollectionBinding) { result.Add(target as IUnprojectedBinding); } //If the target is a collection, and the type of collection is inherited, we will do its loading // via "Post-Projection Loader". Which reloads the inheritance chain by issuing a new query. //We will not handle this case here, instead just mark this for post projection loading. else if (TypesUtil.IsNonPrimitiveCollection(target.Type)) { if (IsManyToManyBinding(target)) { var unprojected = new UnprojectedManyToManyBinding(); unprojected.TargetBinding = target; result.Add(unprojected); } else { if (IsDerivedCollection(target.Type)) { var unprojected = new UnprojectedCollectionBinding(); unprojected.TargetBinding = target; result.Add(unprojected); } } } } return(result); }
public static SimpleType GetMember(SimpleType source, MemberExpression memberExp, MemberExpression translatedMemberExp, TypeTranslationUtil typeTranslationUtil) { SimpleType result; if (source != null) { result = source.GetMemberType(memberExp); if (result != null) { return(result); } } var includes = (source != null) ? source.GetMemberIncludes(memberExp) : new List <IncludeDirective>(); var memberIsCollection = TypesUtil.IsNonPrimitiveCollection(memberExp.Type); var classMapping = typeTranslationUtil.GetMapping <IModelEntityMapping>(memberExp.Member.DeclaringType); if (memberIsCollection && classMapping != null) { //Getting the many-to-many maps for the declaringType var manyToManyRelationship = classMapping.GetManyToManyRelationships() .FirstOrDefault(m => ((MemberExpression)m.RelatedEntitySelector.Body).Member.Name == memberExp.Member.Name); if (manyToManyRelationship != null) { var otherEndSelector = manyToManyRelationship.RelatedEntitySelectorFromMap.Body as MemberExpression; var param = Expression.Parameter(typeTranslationUtil.GetTranslatedType(manyToManyRelationship.MapType), "x"); var translatedOtherEndSelector = typeTranslationUtil.GetMemberExpression (manyToManyRelationship.MapType, otherEndSelector.Member.Name, param); var map = new ManyToManyMapType(manyToManyRelationship.MapType, param.Type, TypesUtil.GetGenericArgumentForBaseType(memberExp.Type, typeof(ICollection <>)), manyToManyRelationship, translatedOtherEndSelector.Member) { Includes = includes }; return(new SimpleType(memberExp.Type, translatedMemberExp.Type) { NonPrimitiveEnumerableItemType = map }); } } result = new SimpleType(memberExp.Type, translatedMemberExp.Type); if (memberIsCollection) { var itemType = TypesUtil.GetGenericArgumentForBaseType(memberExp.Type, typeof(IEnumerable <>)); var translatedItemType = TypesUtil.GetGenericArgumentForBaseType(translatedMemberExp.Type, typeof(IEnumerable <>)); var innerType = new SimpleType(itemType, translatedItemType) { Includes = includes }; result.NonPrimitiveEnumerableItemType = innerType; } else { result.Includes = includes; } return(result); }
private SimpleType GetQueryableType(Type originalType, Type translatedType) { if (!TypesUtil.IsNonPrimitiveCollection(originalType)) { return(new SimpleType(originalType, translatedType)); } else { var itemType = TypesUtil.GetGenericArgumentForBaseType(originalType, typeof(IEnumerable <>)); var translatedItemType = TypesUtil.GetGenericArgumentForBaseType(translatedType, typeof(IEnumerable <>)); return(RuntimeTypes.CreateEnumerable(new SimpleType(itemType, translatedItemType))); } }
private Func <EntityContext, object[], TResult> GetFunc <TResult>(LambdaExpression query) { var analyzer = new CompilableQueryAnalyzer(query, GetTypeTranslationUtil()); var analysisResult = analyzer.GetResult(); //Find L2S.CompiledQuery.Compile<...>() // and invoke the backend compiler; backendCompiledMethod is a Func<,..> var compiledBackendMethod = GetCompileMethod(analysisResult).Invoke(null, new object[] { analysisResult.TranslatedCompilableLambda }); //Compile the client-side part of the expression and get a Func<> // This function the materialized form and works on it (like call a ToList() for instance). object postMaterializationLambda = null; if (analysisResult.PostMaterializationLambda != null) { postMaterializationLambda = analysisResult.PostMaterializationLambda.Compile(); } //l2sCompileResult lambda can return two types // 1. IQueryable // 2. An Entity itself, as a result of the call to First(), Single() etc. if (!TypesUtil.IsNonPrimitiveCollection(analysisResult.MaterializableExpression.Type)) { return((context, args) => { var backendResults = InvokeCompiledMethod(compiledBackendMethod, context as EntityContext, args); var singleObjectMaterializer = Activator.CreateInstance(typeof(SingleObjectMaterializer <>) .MakeGenericType(analysisResult.MaterializableExpression.Type), new object[] { context }); var materializedResult = singleObjectMaterializer.GetType().GetMethod("MakeResult") .Invoke(singleObjectMaterializer, new object[] { backendResults, analysisResult.QueryableType }); return (TResult)InvokePostMaterializationLambda_IfExists(materializedResult, postMaterializationLambda); }); } else { return((context, args) => { var queryType = TypesUtil.GetGenericArgumentForBaseType(analysisResult.MaterializableExpression.Type, typeof(IQueryable <>)); var compiledQuery = Activator.CreateInstance(typeof(CompiledQuery <>).MakeGenericType(queryType), new object[] { GetQueryProvider(context as EntityContext), this, args, compiledBackendMethod, analysisResult.QueryableType.NonPrimitiveEnumerableItemType }); return (TResult)InvokePostMaterializationLambda_IfExists(compiledQuery, postMaterializationLambda); }); } }
protected object LoadObject(IObjectGraph source, Dictionary <object, object> parsedObjects) { if (!source.IsAnonymous) { var instance = source.GetInstance(); if (instance is IEntity) { instance = GetCopyInContextOrAttach(instance as IEntity); } LoadIncludes(source, instance, parsedObjects); return(instance); } else { //Anonymous Types var anonType = source.GetInstanceType(); var ctor = anonType.GetConstructors().Single(); var deserializedIncludes = new Dictionary <PropertyInfo, object>(); foreach (var property in source.GetPropertiesNeedingContextBinding()) { if (!TypesUtil.IsNonPrimitiveCollection(property.PropertyType)) { var propertyValue = LoadObject(source.GetObjectGraphForProperty(property), parsedObjects); deserializedIncludes.Add(property, propertyValue); } else { var collectionItems = source.GetObjectGraphForCollection(property) .Select(itemInfo => LoadObject(itemInfo, parsedObjects)).ToList(); var propertyValue = MakeEnumerable(property.PropertyType, collectionItems); deserializedIncludes.Add(property, propertyValue); } } var ctorArgs = deserializedIncludes.Select(kvp => kvp.Value).ToArray(); return(Activator.CreateInstance(anonType, ctorArgs)); } }
public object SwitchContext(object objects) { var returnType = objects.GetType(); var parsedObjects = new Dictionary <object, object>(); if (!TypesUtil.IsNonPrimitiveCollection(returnType)) { return(LoadObject(new InMemoryInstanceGraph(objects), parsedObjects)); } else { var list = new List <object>(); foreach (var objSource in objects as IEnumerable) { list.Add(LoadObject(new InMemoryInstanceGraph(objSource), parsedObjects)); } return(FillEnumerable(objects, list)); } }
private List <IRelatedBinding> GetInheritanceBindings(IEnumerable <IRequestedBinding> requestedBindings) { var result = new List <IRelatedBinding>(); foreach (var target in requestedBindings.Where(b => !TypesUtil.IsNonPrimitiveCollection(b.Type))) { //Not a collection. Add Inheritance Bindings if there are any. var inheritanceExpressions = GetInheritanceExpressions(target.Type, target.TranslatedExpression); foreach (var expression in inheritanceExpressions) { var binding = new InheritanceBinding { TargetBinding = target, TranslatedExpression = expression }; result.Add(binding); } } return(result); }
protected virtual List <IncludeDirective> GetMemberIncludes(MemberExpression memberExp) { var newIncludes = new List <IncludeDirective>(); var memberIsNotCollection = !TypesUtil.IsNonPrimitiveCollection(memberExp.Type); Includes.ForEach(inc => { var includeExpression = inc.GetSelector().Body as MemberExpression; if (memberIsNotCollection) { var innermostMember = ExpressionUtil.GetInnermostMemberExpression(includeExpression); if (innermostMember.Member == memberExp.Member && includeExpression.Expression is MemberExpression) { var slicedExpression = ExpressionUtil.ReplaceInnermostMemberExpressionWithParameter(includeExpression) as MemberExpression; if (inc is IIncludeInCollectionDirective) { newIncludes.Add(IncludeDirectiveUtil.GetIncludeInCollectionDirective(slicedExpression, (inc as IIncludeInCollectionDirective).GetFieldSelector())); } else { newIncludes.Add(IncludeDirectiveUtil.GetIncludeDirective(slicedExpression)); } } } else { if (inc is IIncludeInCollectionDirective && ExpressionUtil.IsEquivalent(inc.GetSelector().Body, memberExp)) { newIncludes.Add(IncludeDirectiveUtil.GetIncludeDirective ((inc as IIncludeInCollectionDirective).GetFieldSelector())); } } }); return(newIncludes); }
protected void LoadIncludes(IObjectGraph source, object instance, Dictionary <object, object> parsedObjects) { if (parsedObjects.ContainsKey(instance)) { return; } //Add it to the parsed objects list, so that we can avoid going through circular relationships. parsedObjects.Add(instance, null); if (source.IsCollection) { var sourceCollection = source.GetSourceCollection(); var ctr = 0; foreach (var item in (instance as IEnumerable)) { LoadIncludes(sourceCollection[ctr++], item, parsedObjects); } } else { foreach (var property in source.GetPropertiesNeedingContextBinding()) { if (!TypesUtil.IsNonPrimitiveCollection(property.PropertyType)) { //If the instance is an Entity, we treat property setting differently. // This is because setters will automatically trigger Reverse Reference setters. if (instance is IEntity) { var propValFromSource = source.GetPropertyValue(property); var loadedValue = property.GetValue(instance); //If the property is already loaded in our current instance, we should not touch it. // Yet, if they (current instance and the source) refer to the same value, we should attach includes. //If they are NOT the same, we do nothing. (Since the user changed the property, can't overwrite.) if (IsPropertyLoadedOnEntity(instance, property)) { if (loadedValue != null && loadedValue is IEntity && ((IEntity)loadedValue).IsEquivalent((IEntity)propValFromSource)) { LoadIncludes(source.GetObjectGraphForProperty(property), loadedValue, parsedObjects); } } //Property is not loaded on the current instance. Go ahead and add it via Materialization methods. else { if (source.GetPropertyValue(property) != null) { var propertyValue = LoadObject(source.GetObjectGraphForProperty(property), parsedObjects); var intermediateContainer = GetBackingContainerForProperty(instance as IEntity, property); intermediateContainer.MaterializationAddReference((propertyValue as IEntity)._getIntermediateEntity()); } } } //Instance is not an IEntity, we can just set the property value. else { if (source.GetPropertyValue(property) != null) { var propertyValue = LoadObject(source.GetObjectGraphForProperty(property), parsedObjects); property.SetValue(instance, propertyValue); } } } //This property is a collection. else { var entityList = source.GetObjectGraphForCollection(property) .Select(collItemSource => LoadObject(collItemSource, parsedObjects)).ToList(); if (IsManyToMany(property)) { //Many-to-Many collection can only exist in Entities, hence the cast. AddToManyToManyCollection((IEntity)instance, property, entityList); } else { SetEnumerableProperty(instance, property, MakeEnumerable(property.PropertyType, entityList)); } } } } }
//Serialization of entities should consider the included fields. // - If A.B is defined as an include on A at the time of materialization, B should also be serialized // and re-attached when A is deserialized. private SerializableObjectGraph CreateObjectGraph(object entity) { var sourceType = entity.GetType(); //If this is a collection, create a graph for each item in the collection. if (TypesUtil.IsNonPrimitiveCollection(sourceType)) { var list = new List <IObjectGraph>(); foreach (object obj in entity as IEnumerable) { list.Add(CreateObjectGraph(obj)); } return(new SerializableCollection { Collection = list, InstanceType = sourceType }); } else { var serializableInstance = new SerializableInstance { Object = entity, InstanceType = entity.GetType() }; if (entity is IEntity) { var materializationIncludes = GetIncludeExpressions((entity as IEntity)._getIntermediateEntity().IncludeDirectives); foreach (var includeExps in materializationIncludes) { AddIncludes(serializableInstance, includeExps.FieldChain, includeExps.IncludesInCollection); } } else { if (TypesUtil.IsCompilerGeneratedAnonymousType(sourceType)) { serializableInstance.Object = null; serializableInstance.InstanceType = sourceType; } var properties = (entity is IEntity) ? sourceType.GetProperties() .Where(p => typeof(IEntity).IsAssignableFrom(p.PropertyType) || typeof(IEntityCollection).IsAssignableFrom(p.PropertyType)).ToArray() : (TypesUtil.IsPrimitiveDataType(sourceType) || sourceType.IsArray || TypesUtil.IsNonPrimitiveCollection(sourceType) ? new PropertyInfo[] {} : sourceType.GetProperties()); foreach (var prop in properties) { var propVal = prop.GetValue(entity, null); //Primitive types can be stored as is. if (TypesUtil.IsPrimitiveDataType(prop.PropertyType)) { serializableInstance.IncludedMembers.Add ( prop, new SerializableInstance { Object = propVal, InstanceType = prop.PropertyType } ); continue; } //This is a single object (possibly an entity); but not a primitive type or a collection if (!TypesUtil.IsNonPrimitiveCollection(prop.PropertyType)) { serializableInstance.IncludedMembers.Add ( prop, CreateObjectGraph(propVal) ); } //Collection of non-primitive types else if (TypesUtil.IsNonPrimitiveCollection(prop.PropertyType)) { var itemsInCollection = new List <IObjectGraph>(); foreach (var item in (propVal as IEnumerable)) { itemsInCollection.Add(CreateObjectGraph(item)); } serializableInstance.IncludedMembers.Add ( prop, new SerializableCollection { Collection = itemsInCollection, InstanceType = prop.PropertyType } ); } } } return(serializableInstance); } }
private void AddIncludes(SerializableObjectGraph objectGraph, MemberExpression includedPropertyChain, IEnumerable <MemberExpression> collectionIncludes) { var memberExp = ExpressionUtil.GetInnermostMemberExpression(includedPropertyChain); var propInfo = objectGraph.GetInstance().GetType().GetProperty(memberExp.Member.Name); if (IsPropertyLoadedOnEntity(objectGraph.GetInstance(), propInfo)) { var propVal = propInfo.GetValue(objectGraph.GetInstance(), null); if (propVal == null) { return; } if (TypesUtil.IsNonPrimitiveCollection(propInfo.PropertyType)) { var collInclude = objectGraph.IncludedMembers.ContainsKey(propInfo) ? objectGraph.IncludedMembers[propInfo] : null; if (collInclude == null) { var list = new List <IObjectGraph>(); foreach (var item in (propVal as IEnumerable)) { list.Add(new SerializableInstance { Object = item, InstanceType = item.GetType() }); } collInclude = new SerializableCollection { Collection = list, InstanceType = propInfo.PropertyType }; objectGraph.IncludedMembers.Add(propInfo, collInclude); } if (collectionIncludes != null) { foreach (SerializableObjectGraph instanceWrapper in (collInclude as SerializableCollection).Collection) { foreach (var include in collectionIncludes) { AddIncludes(instanceWrapper, include, null); } } } } else { var fieldInclude = objectGraph.IncludedMembers.ContainsKey(propInfo) ? objectGraph.IncludedMembers[propInfo] : null; if (fieldInclude == null) { fieldInclude = new SerializableInstance { Object = propVal, InstanceType = propInfo.PropertyType }; objectGraph.IncludedMembers.Add(propInfo, fieldInclude); } if (includedPropertyChain.GetDepth() > 1) { AddIncludes(fieldInclude, ExpressionUtil.ReplaceInnermostMemberExpression(includedPropertyChain, Expression.Parameter(memberExp.Type, "x")) as MemberExpression, collectionIncludes); } } } }