Esempio n. 1
0
        public static IQueryable SelectProperties <T>(this IQueryable <T> queryable, IEnumerable <string> propertyNames)
        {
            // get propertyinfo's from original type
            var properties = typeof(T).GetProperties().Where(p => propertyNames.Contains(p.Name));
            // Creating anonymous type using dictionary of property name and property type
            var genericTypeName          = queryable.ElementType.FullName;
            var propertyInfos            = properties as PropertyInfo[] ?? properties.ToArray();
            var anonymousType            = AnonymousTypeUtils.CreateType(genericTypeName, propertyInfos.ToDictionary(p => p.Name, p => p.PropertyType));
            var anonymousTypeConstructor = anonymousType.GetConstructors().Single();
            var anonymousTypeMembers     = anonymousType.GetProperties().Cast <MemberInfo>().ToArray();

            // Create the x => expression
            var lambdaParameterExpression = Expression.Parameter(typeof(T));
            // Create the x.<propertyName>'s
            var propertyExpressions = propertyInfos.Select(p => Expression.Property(lambdaParameterExpression, p));

            // Create the new {} expression using
            var anonymousTypeNewExpression = Expression.New(anonymousTypeConstructor, propertyExpressions, anonymousTypeMembers);

            var selectLambdaMethod         = GetExpressionLambdaMethod(lambdaParameterExpression.Type, anonymousType);
            var selectBodyLambdaParameters = new object[] { anonymousTypeNewExpression, new[] { lambdaParameterExpression } };
            var selectBodyLambdaExpression = (LambdaExpression)selectLambdaMethod.Invoke(null, selectBodyLambdaParameters);

            var selectMethod = GetQueryableSelectMethod(typeof(T), anonymousType);
            //TODO: Is it possible to infer the type and hence allow for IQueryable<T>
            var selectedQueryable = selectMethod.Invoke(null, new object[] { queryable, selectBodyLambdaExpression }) as IQueryable;

            return(selectedQueryable);
        }
        public void CreateObject_GetHashCode_UsesExpectedAlgorithm()
        {
            var objA = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "a", 1 },
                { "b", "test" },
                { "c", new DateTime(2014, 1, 1) },
            });

            // Seems questionable to hardcode in the algorithm in a test,
            // but since the real thing is done through generated IL then it seems legit maybe?
            int       hash           = 0;
            const int hashMultiplier = -1521134295;

            foreach (var field in objA.GetType().GetFields(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.DeclaredOnly))
            {
                unchecked
                {
                    hash = (hash * hashMultiplier) + field.Name.GetHashCode();
                }
            }
            unchecked
            {
                hash = (hash * hashMultiplier) + 1.GetHashCode();
                hash = (hash * hashMultiplier) + "test".GetHashCode();
                hash = (hash * hashMultiplier) + new DateTime(2014, 1, 1).GetHashCode();
            }
            Assert.AreEqual(hash, objA.GetHashCode());
        }
        public void CreateObject_ParentClassWithDefaultConstructor_ReusePropertyName()
        {
            var typeDictionary = new Dictionary <string, Type>
            {
                { "a", typeof(string) },
                { "Value", typeof(int) }
            };
            var parentType    = typeof(TestClassWithDefaultConstructor);
            var anonymousType = AnonymousTypeUtils.CreateType(typeDictionary, isMutable: false, parent: parentType);

            var obj = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "a", "1" },
                { "Value", 3 },
            }, anonymousType);

            Assert.AreEqual(parentType, obj.GetType().BaseType);

            // If we get the value of the property directly from our new type, then it should be the one we set.
            var valueProperty = obj.GetType().GetProperty("Value", System.Reflection.BindingFlags.DeclaredOnly | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);

            Assert.IsNotNull(valueProperty);
            Assert.AreEqual(3, valueProperty.GetValue(obj));

            // We don't override the base class property (and can't if it isn't virtual),
            // so the value when cast as the base type should still be what was set in the default constructor.
            var objTestClass = obj as TestClassWithDefaultConstructor;

            Assert.AreEqual(2, objTestClass.Value);
        }
        public void CreateTypeDefinition_LargeNumberOfProperties(int propertyCount)
        {
            var propertyNames = Enumerable.Range(0, propertyCount).Select(i => "Property" + i.ToString()).ToList();

            var genericTypeDefinition = AnonymousTypeUtils.CreateGenericTypeDefinition(propertyNames);

            Assert.AreEqual(propertyCount, genericTypeDefinition.GetProperties().Length);
        }
        public void CreateGenericTypeDefinition_ParentClassWithConstructor()
        {
            var expectedException = Assert.Throws <ArgumentException>(() => AnonymousTypeUtils.CreateGenericTypeDefinition(
                                                                          propertyNames: new[] { "b", "a" },
                                                                          isMutable: false,
                                                                          parent: typeof(TestClassWithConstructor)
                                                                          ));

            StringAssert.Contains("default constructor", expectedException.Message);
        }
        public void CreateType_SameTypeTwice()
        {
            var typeDictionary = new Dictionary <string, Type>
            {
                { "a", typeof(int) }
            };
            var t1 = AnonymousTypeUtils.CreateType(typeDictionary.ToList());
            var t2 = AnonymousTypeUtils.CreateType(typeDictionary.ToList());

            Assert.AreSame(t1, t2);
        }
        public void CreateGenericTypeDefinition_ParentClass()
        {
            var  parentType = typeof(TestClass);
            Type anonymousGenericTypeDefinition = AnonymousTypeUtils.CreateGenericTypeDefinition(
                propertyNames: new[] { "b", "a" },
                isMutable: false,
                parent: parentType
                );

            Assert.IsTrue(anonymousGenericTypeDefinition.IsSubclassOf(parentType));
        }
        public void CreateObject_ToString()
        {
            var obj = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "b", "test" },
                { "a", 1 },
                { "c", new DateTime(2014, 1, 1) },
                { "d", new object() },
            });
            var expectedString = "{ b = test, a = 1, c = 1/1/2014 12:00:00 AM, d = System.Object }";

            Assert.AreEqual(expectedString, obj.ToString());
        }
        public void CreateObject_Equals_EmptyObject()
        {
            var objA = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "a", 1 },
                { "b", "test" },
                { "c", new DateTime(2014, 1, 1) },
                { "d", new object() },
            });

            var objB = new object();

            Assert.IsFalse(objA.Equals(objB));
        }
        public void CreateObject_GetHashCode_EqualObjects()
        {
            var valueDictionary = new Dictionary <string, object>
            {
                { "b", "test" },
                { "a", 1 },
                { "c", new DateTime(2014, 1, 1) },
                { "d", new object() },
            };

            var objA = AnonymousTypeUtils.CreateObject(valueDictionary);
            var objB = AnonymousTypeUtils.CreateObject(valueDictionary);

            Assert.AreNotSame(objA, objB);
            Assert.AreEqual(objA.GetHashCode(), objB.GetHashCode());
        }
        public void CreateObject_Properties()
        {
            var obj = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "b", "test" },
                { "a", 1 },
            });

            var propertyA = obj.GetType().GetProperty("a");

            Assert.AreEqual(1, propertyA.GetValue(obj));

            var propertyB = obj.GetType().GetProperty("b");

            Assert.AreEqual("test", propertyB.GetValue(obj));
        }
        public void CreateObject_Equals_RealAnonymousType()
        {
            var objA = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "a", 1 },
                { "b", "test" },
                { "c", new DateTime(2014, 1, 1) },
                { "d", new object() },
            });

            var objB = new { a = 1, b = "test", c = new DateTime(2014, 1, 1), d = new object() };

            Assert.AreNotSame(objA, objB);
            Assert.IsTrue(objA.Equals(objA));
            Assert.IsFalse(objA.Equals(objB));
            Assert.IsFalse(objB.Equals(objA));
        }
        public void CreateObject_NullValues()
        {
            var obj = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "a", null },
                { "b", null },
            });

            var propertyA = obj.GetType().GetProperty("a");

            Assert.AreEqual(propertyA.PropertyType, typeof(object));
            Assert.IsNull(propertyA.GetValue(obj));

            var propertyB = obj.GetType().GetProperty("b");

            Assert.AreEqual(propertyB.PropertyType, typeof(object));
            Assert.IsNull(propertyB.GetValue(obj));
        }
        public void CreateType_CommaInPropertyName()
        {
            // If we combine the property names with a comma delimiter (without any escaping),
            // then these two types would have the same property string in their name.
            var t1 = AnonymousTypeUtils.CreateType(new Dictionary <string, Type>
            {
                { "a", typeof(int) },
                { "b,c", typeof(int) }
            });
            var t2 = AnonymousTypeUtils.CreateType(new Dictionary <string, Type>
            {
                { "a,b", typeof(int) },
                { "c", typeof(int) },
            });

            Assert.AreNotSame(t1, t2);
            Assert.AreNotEqual(t1, t2);
        }
        public void CreateType(bool isMutable)
        {
            var typeDictionary = new Dictionary <string, Type>
            {
                { "b", typeof(string) },
                { "a", typeof(int) }
            };
            var anonymousType = AnonymousTypeUtils.CreateType(typeDictionary, isMutable: isMutable);

            Assert.AreEqual(2, anonymousType.GetProperties().Length);

            var propertyA = anonymousType.GetProperty("a");

            Assert.IsNotNull(propertyA);
            Assert.AreEqual(typeof(int), propertyA.PropertyType);
            Assert.IsTrue(propertyA.CanRead);
            Assert.AreEqual(isMutable, propertyA.CanWrite);

            var propertyB = anonymousType.GetProperty("b");

            Assert.IsNotNull(propertyB);
            Assert.AreEqual("b", propertyB.Name);
            Assert.AreEqual(typeof(string), propertyB.PropertyType);
            Assert.IsTrue(propertyB.CanRead);
            Assert.AreEqual(isMutable, propertyB.CanWrite);

            var constructors = anonymousType.GetConstructors();

            Assert.AreEqual(1, constructors.Length);

            var constructorParameters = constructors.Single().GetParameters();

            Assert.AreEqual(2, constructorParameters.Length);

            Assert.AreEqual("b", constructorParameters.ElementAt(0).Name);
            Assert.AreEqual("a", constructorParameters.ElementAt(1).Name);

            StringAssert.StartsWith("<>f__LatticeUtilsAnonymousType", anonymousType.Name);
            StringAssert.EndsWith("`2", anonymousType.Name);
        }
        public void CreateObject_ParentClassWithDefaultConstructor()
        {
            var typeDictionary = new Dictionary <string, Type>
            {
                { "b", typeof(string) },
                { "a", typeof(int) }
            };
            var parentType    = typeof(TestClassWithDefaultConstructor);
            var anonymousType = AnonymousTypeUtils.CreateType(typeDictionary, isMutable: false, parent: parentType);

            var obj = AnonymousTypeUtils.CreateObject(new Dictionary <string, object>
            {
                { "b", "test" },
                { "a", 1 },
            }, anonymousType);

            Assert.AreEqual(parentType, obj.GetType().BaseType);

            var objTestClass = obj as TestClassWithDefaultConstructor;

            Assert.AreEqual(2, objTestClass.Value);
        }
        /// <summary>
        /// Constructs an anonymous function that returns a DbExpression and expects an Anonymous Type.
        /// Supports the ability to dynamically create the following lambda:
        /// p => new {
        ///   Column1 = p.Property("l").Property("Column1")
        /// }
        /// </summary>
        /// <param name="fields">List of column names</param>
        /// <returns>Func<DbExpression,T></returns>
        public static LambdaExpression CreateLambdaExpression(Dictionary <string, string> fields)
        {
            Type type = Type.GetType("System.Func`2");

            Type[] anonymousTypeArguments = fields.Keys.Select(p => typeof(DbPropertyExpression)).ToArray();
            Type   anonymousType          = AnonymousTypeUtils.CreateGenericTypeDefinition(fields.Keys);

            anonymousType = anonymousType.MakeGenericType(anonymousTypeArguments);

            Type[] typeArguments = new[] { typeof(DbExpression), anonymousType };
            var    lambdaType    = type.MakeGenericType(typeArguments);

            var pParam = Expression.Parameter(typeof(DbExpression), "p");

            ParameterExpression[] parameters = { pParam };

            ConstructorInfo constructor = anonymousType.GetConstructors().SingleOrDefault();

            MethodInfo memberInfo = typeof(DbExpressionBuilder).GetMethods().FirstOrDefault(m => m.ToString() == "System.Data.Entity.Core.Common.CommandTrees.DbPropertyExpression Property(System.Data.Entity.Core.Common.CommandTrees.DbExpression, System.String)");

            List <Expression> argumentList = new List <Expression>();
            List <MemberInfo> membersList  = new List <MemberInfo>();

            foreach (string field in fields.Keys)
            {
                Expression[] leftTableExpressions = { pParam, Expression.Constant(fields[field]) };
                Expression   methodCallExpression = Expression.Call(null, memberInfo, leftTableExpressions);

                Expression[] secondPropertyExpressions = { methodCallExpression, Expression.Constant(field) };
                argumentList.Add(Expression.Call(null, memberInfo, secondPropertyExpressions));
                membersList.Add(anonymousType.GetMembers().FirstOrDefault(m => m.ToString() == string.Format("System.Data.Entity.Core.Common.CommandTrees.DbPropertyExpression {0}", field)));
            }

            var body = Expression.New(constructor, argumentList, membersList);

            return(Expression.Lambda(lambdaType, body, parameters));
        }
        public void CreateGenericTypeDefinition(bool isMutable)
        {
            var propertyNames = new[] { "b", "a" };

            var anonymousGenericTypeDefinition = AnonymousTypeUtils.CreateGenericTypeDefinition(propertyNames, isMutable: isMutable);

            Assert.AreEqual(2, anonymousGenericTypeDefinition.GetProperties().Length);

            var propertyA = anonymousGenericTypeDefinition.GetProperty("a");

            Assert.IsNotNull(propertyA);
            Assert.IsTrue(propertyA.PropertyType.IsGenericParameter);
            Assert.IsTrue(propertyA.CanRead);
            Assert.AreEqual(isMutable, propertyA.CanWrite);

            var propertyB = anonymousGenericTypeDefinition.GetProperty("b");

            Assert.IsNotNull(propertyB);
            Assert.AreEqual("b", propertyB.Name);
            Assert.IsTrue(propertyB.PropertyType.IsGenericParameter);
            Assert.IsTrue(propertyB.CanRead);
            Assert.AreEqual(isMutable, propertyB.CanWrite);

            var constructors = anonymousGenericTypeDefinition.GetConstructors();

            Assert.AreEqual(1, constructors.Length);

            var constructorParameters = constructors.Single().GetParameters();

            Assert.AreEqual(2, constructorParameters.Length);

            Assert.AreEqual("b", constructorParameters.ElementAt(0).Name);
            Assert.AreEqual("a", constructorParameters.ElementAt(1).Name);

            StringAssert.StartsWith("<>f__LatticeUtilsAnonymousType", anonymousGenericTypeDefinition.Name);
            StringAssert.EndsWith("`2", anonymousGenericTypeDefinition.Name);
        }
        /// <summary>
        /// Selects the properties from type <c>T</c> from the specified queryable.
        /// </summary>
        /// <remarks>
        /// This basically lets you do queryable.Select(x => new { x.Property1, x.Property2 }) without
        /// having to know which properties you want to select at compile time.
        /// </remarks>
        /// <typeparam name="T">the type of entity from which to select the properties</typeparam>
        /// <param name="queryable">the queryable to apply the select to</param>
        /// <param name="propertyNames">the names of the properties to select</param>
        /// <returns>a queryable of dynamically generated anonymous types</returns>
        public IQueryable SelectProperties <T>(IQueryable <T> queryable, ISet <string> propertyNames)
        {
            var properties = typeof(T).GetProperties().Where(p => propertyNames.Contains(p.Name));

            var entityParameterExpression = Expression.Parameter(typeof(T));
            var propertyExpressions       = properties.Select(p => Expression.Property(entityParameterExpression, p));

            var anonymousType            = AnonymousTypeUtils.CreateType(properties.ToDictionary(p => p.Name, p => p.PropertyType));
            var anonymousTypeConstructor = anonymousType.GetConstructors().Single();
            var anonymousTypeMembers     = anonymousType.GetProperties().Cast <MemberInfo>().ToArray();

            // It's important to include the anonymous type members in the New expression, otherwise EntityFramework
            // won't recognize this as the constructor of an anonymous type.
            var anonymousTypeNewExpression = Expression.New(anonymousTypeConstructor, propertyExpressions, anonymousTypeMembers);

            var selectLambdaMethod         = GetExpressionLambdaMethod(entityParameterExpression.Type, anonymousType);
            var selectBodyLambdaParameters = new object[] { anonymousTypeNewExpression, new[] { entityParameterExpression } };
            var selectBodyLambdaExpression = (LambdaExpression)selectLambdaMethod.Invoke(null, selectBodyLambdaParameters);

            var selectMethod      = GetQueryableSelectMethod(typeof(T), anonymousType);
            var selectedQueryable = selectMethod.Invoke(null, new object[] { queryable, selectBodyLambdaExpression }) as IQueryable;

            return(selectedQueryable);
        }
        public void CreateType_MultipleThreads()
        {
            // Our goal with this test is to have multiple threads creating the same type at the same time.
            // This should help us detect if there are issues with our locking (like in Issue #2).

            // The number of types we create will be iterationCount * threadCount * typeCount
            const int iterationCount = 100;
            const int threadCount    = 8;
            const int typeCount      = 5;

            for (var i = 0; i < iterationCount; i++)
            {
                // We'll generate the property names ahead of time, and then create one type per property (per task).
                var propertyNames = Enumerable.Range(0, typeCount).Select(k => string.Format("MultiThreadTestProperty{0}.{1}", i, k)).ToList();

                // Create several tasks that will all try to create the same types at once.
                var tasks = new List <Task>(threadCount);
                for (var j = 0; j < threadCount; j++)
                {
                    var task = new TaskFactory().StartNew(() =>
                    {
                        foreach (var propertyName in propertyNames)
                        {
                            AnonymousTypeUtils.CreateObject(new Dictionary <string, object> {
                                { propertyName, "test" }
                            });
                        }
                    });
                    tasks.Add(task);
                }

                // Wait for all of the tasks to finish
                // If anything goes wrong in the above code, the exception will be thrown here.
                Task.WaitAll(tasks.ToArray());
            }
        }
        public void CreateObject_Equals_EqualObjects_LargeNumberOfProperties()
        {
            var valueDictionary = new Dictionary <string, object>
            {
                { "b", "test" },
                { "a", 1 },
                { "c", new DateTime(2014, 1, 1) },
                { "d", new object() },
                { "e", 1 },
                { "f", 2 },
                { "g", 3 },
                { "h", 4 },
                { "i", 5 },
                { "j", 6 },
                { "k", 7 },
                { "l", 8 },
                { "m", 1 },
                { "n", 2 },
                { "o", 3 },
                { "p", 4 },
                { "q", 5 },
                { "r", 6 },
                { "s", 7 },
                { "t", 8 },
            };

            var objA = AnonymousTypeUtils.CreateObject(valueDictionary);
            var objB = AnonymousTypeUtils.CreateObject(valueDictionary);

            Assert.AreNotSame(objA, objB);
            Assert.AreEqual(objA, objB);
            Assert.IsTrue(objA.Equals(objA));
            Assert.IsTrue(objB.Equals(objB));
            Assert.IsTrue(objA.Equals(objB));
            Assert.IsTrue(objB.Equals(objA));
        }
        private Type CreateLambbda(out Expression <Func <T, dynamic> > lambda)
        {
            /*
             * Based in the follwing:
             *
             * var projector = rep.PropertySelectBuilder(blog)
             *      .Select(p => p.Name)
             *      .Include<Post>(m => m.Posts, p => p.Text)
             *      .Build();
             *
             *
             * Output lambda to be used as expression in:
             *
             * context.Set<T>().
             *  Where(p => p.Id == id).
             *  Select(lamdba.Expression).
             *  Single();
             *
             *
             * where lambda will look (using AllProjections in the builder), using example projector above
             *
             * p = new
             * {
             *  p => p.Name,
             *  Posts =     from post in context.Set<Post>()
             *              where post.BlogId == _id
             *              select new
             *              {
             *                  Text = pp.Text
             *              }
             * }
             */

            List <KeyValuePair <string, Type> > anonymousTypeProperties = new List <KeyValuePair <string, Type> >();
            List <Expression>   anonymousTypePropertiesValues           = new List <Expression>();
            ParameterExpression lambdaParameter = Expression.Parameter(typeof(T), "p");

            foreach (var projection in AllProjections.BaseEntityProjections)
            {
                var projectionLambda = projection as LambdaExpression;

                MemberExpression member = ParameterHelper.GetMemberExpression(projectionLambda);

                var propertyInfo = (PropertyInfo)member.Member;
                var propertyName = propertyInfo.Name;
                var propertyType = propertyInfo.PropertyType;

                var memberAccess = Expression.Property(lambdaParameter, propertyName);

                anonymousTypeProperties.Add(new KeyValuePair <string, Type>(propertyName, propertyType));
                anonymousTypePropertiesValues.Add(memberAccess);
            }

            foreach (var navigationProperty in AllProjections.NavigationPropertiesProjections)
            {
                var navigationProperyType = navigationProperty.Type;

                // Creates the <T>.where(p => p.id == id) part of the expression
                MethodCallExpression whereCallExpression = CreateWhereCall <T>(_id, navigationProperyType);

                ParameterExpression p1 = Expression.Parameter(navigationProperyType, "p1");
                var navigationPropertyAnoymousTypeProperties = new List <KeyValuePair <string, Type> >();
                List <MemberExpression> navigationPropertyAnoymousTypePropertiesValues = new List <MemberExpression>();
                foreach (var projection in navigationProperty.Projections)
                {
                    var navigationPropertyProjection = projection as LambdaExpression;

                    MemberExpression member = ParameterHelper.GetMemberExpression(navigationPropertyProjection);

                    var propertyInfo = (PropertyInfo)member.Member;
                    var propertyName = propertyInfo.Name;
                    var propertyType = propertyInfo.PropertyType;

                    var memberAccess = Expression.Property(p1, propertyName);

                    navigationPropertyAnoymousTypeProperties.Add(new KeyValuePair <string, Type>(propertyName, propertyType));
                    navigationPropertyAnoymousTypePropertiesValues.Add(memberAccess);
                }

                var anonymousTypeOfNavigationPropertyProjection =
                    AnonymousTypeUtils.CreateType(navigationPropertyAnoymousTypeProperties);
                Type typeOfSubProj = null;
                var  anonymousTypeOfNavigationPropertyProjectionConstructor = anonymousTypeOfNavigationPropertyProjection
                                                                              .GetConstructor(navigationPropertyAnoymousTypeProperties.Select(kv => kv.Value).ToArray());
                typeOfSubProj = anonymousTypeOfNavigationPropertyProjectionConstructor.ReflectedType;

                var selectMethod        = typeof(Queryable).GetMethods().Where(m => m.Name == "Select").ToList()[0];
                var genericSelectMethod = selectMethod.MakeGenericMethod(navigationProperyType, typeOfSubProj);

                var newInstanceOfTheGenericType = Expression.New(anonymousTypeOfNavigationPropertyProjectionConstructor,
                                                                 navigationPropertyAnoymousTypePropertiesValues);

                var projectionLamdba = Expression.Lambda(newInstanceOfTheGenericType, p1);

                MethodCallExpression selctCallExpression = Expression.Call(
                    genericSelectMethod,
                    whereCallExpression,
                    projectionLamdba);

                var provider = ((IQueryable)_context.Set <T>()).Provider;
                // TODO, Is it ok to assume navigation properties has the same provider?
                var theMethods    = typeof(IQueryProvider).GetMethods();
                var createQMethd  = theMethods.Where(name => name.Name == "CreateQuery").ToList()[1];
                var speciifMethod =
                    createQMethd.MakeGenericMethod(anonymousTypeOfNavigationPropertyProjectionConstructor.ReflectedType);
                var navigationProppertyQueryWithProjection1 = speciifMethod.Invoke(provider, new object[] { selctCallExpression });

                Type genericFunc         = typeof(IEnumerable <>);
                Type funcOfTypeOfSubProj = genericFunc.MakeGenericType(typeOfSubProj);

                var allMethodsOnEnumerableClass = typeof(Enumerable).GetMethods();
                var genericToListMethod         = allMethodsOnEnumerableClass.Where(m => m.Name == "ToList").ToList()[0];

                var toListOfTypeOfSubProj = genericToListMethod.MakeGenericMethod(typeOfSubProj);

                MethodCallExpression toListExpression11 = Expression.Call(
                    toListOfTypeOfSubProj,
                    Expression.Constant(navigationProppertyQueryWithProjection1));

                anonymousTypeProperties.Add(new KeyValuePair <string, Type>(navigationProperty.Name, funcOfTypeOfSubProj));
                anonymousTypePropertiesValues.Add(toListExpression11);
            }

            var projectedEntityAnonymousType = AnonymousTypeUtils.CreateType(anonymousTypeProperties);

            var constructor = projectedEntityAnonymousType.GetConstructor(anonymousTypeProperties.Select(p => p.Value).ToArray());

            var anonymousTypeInstance = Expression.New(constructor, anonymousTypePropertiesValues);

            lambda = Expression.Lambda <Func <T, dynamic> >(anonymousTypeInstance, lambdaParameter);
            return(projectedEntityAnonymousType);
        }
Esempio n. 23
0
        public T RetrieveByIdOld <T>(int id, ISelectPropertyBuilder <T> selectedSelectProperties) where T : class, IEntity
        {
            // The query will be projected onto an anonymous type.
            List <KeyValuePair <string, Type> > anonymousTypeProperties = new List <KeyValuePair <string, Type> >();
            List <Expression>   anonymousTypePropertiesValues           = new List <Expression>();
            ParameterExpression lambdaParameter = Expression.Parameter(typeof(T), "p");

            foreach (var projection in selectedSelectProperties.AllProjections.BaseEntityProjections)
            {
                var projectionLambda = projection as LambdaExpression;

                MemberExpression member = CreateMemberExpression(projectionLambda);

                var propertyInfo = (PropertyInfo)member.Member;
                var propertyName = propertyInfo.Name;
                var propertyType = propertyInfo.PropertyType;

                var memberAccess = Expression.Property(lambdaParameter, propertyName);

                anonymousTypeProperties.Add(new KeyValuePair <string, Type>(propertyName, propertyType));
                anonymousTypePropertiesValues.Add(memberAccess);
            }

            foreach (var navigationProperty in selectedSelectProperties.AllProjections.NavigationPropertiesProjections)
            {
                var navigationProperyType = navigationProperty.Type;

                // Creates the <T>.where(p => p.id == id) part of the expression
                MethodCallExpression whereCallExpression = CreateWhereCall <T>(id, navigationProperyType);

                ParameterExpression p1 = Expression.Parameter(navigationProperyType, "p1");
                var navigationPropertyAnoymousTypeProperties = new List <KeyValuePair <string, Type> >();
                List <MemberExpression> navigationPropertyAnoymousTypePropertiesValues = new List <MemberExpression>();
                foreach (var projection in navigationProperty.Projections)
                {
                    var navigationPropertyProjection = projection as LambdaExpression;

                    MemberExpression member = CreateMemberExpression(navigationPropertyProjection);

                    var propertyInfo = (PropertyInfo)member.Member;
                    var propertyName = propertyInfo.Name;
                    var propertyType = propertyInfo.PropertyType;

                    var memberAccess = Expression.Property(p1, propertyName);

                    navigationPropertyAnoymousTypeProperties.Add(new KeyValuePair <string, Type>(propertyName, propertyType));
                    navigationPropertyAnoymousTypePropertiesValues.Add(memberAccess);
                }

                var  anonymousTypeOfNavigationPropertyProjection = AnonymousTypeUtils.CreateType(navigationPropertyAnoymousTypeProperties);
                Type typeOfSubProj = null;
                var  anonymousTypeOfNavigationPropertyProjectionConstructor = anonymousTypeOfNavigationPropertyProjection
                                                                              .GetConstructor(navigationPropertyAnoymousTypeProperties.Select(kv => kv.Value).ToArray());
                typeOfSubProj = anonymousTypeOfNavigationPropertyProjectionConstructor.ReflectedType;

                var selectMethod        = typeof(Queryable).GetMethods().Where(m => m.Name == "Select").ToList()[0];
                var genericSelectMethod = selectMethod.MakeGenericMethod(navigationProperyType, typeOfSubProj);

                var newInstanceOfTheGenericType = Expression.New(anonymousTypeOfNavigationPropertyProjectionConstructor, navigationPropertyAnoymousTypePropertiesValues);

                var projectionLamdba = Expression.Lambda(newInstanceOfTheGenericType, p1);

                MethodCallExpression selctCallExpression = Expression.Call(
                    genericSelectMethod,
                    whereCallExpression,
                    projectionLamdba);

                var provider      = ((IQueryable)context.Set <T>()).Provider; // TODO, Is it ok to assube navigation properties has the same provider?
                var theMethods    = typeof(IQueryProvider).GetMethods();
                var createQMethd  = theMethods.Where(name => name.Name == "CreateQuery").ToList()[1];
                var speciifMethod = createQMethd.MakeGenericMethod(anonymousTypeOfNavigationPropertyProjectionConstructor.ReflectedType);
                var navigationProppertyQueryWithProjection1 = speciifMethod.Invoke(provider, new object[] { selctCallExpression });

                Type genericFunc         = typeof(IEnumerable <>);
                Type funcOfTypeOfSubProj = genericFunc.MakeGenericType(typeOfSubProj);

                var allMethodsOnEnumerableClass = typeof(Enumerable).GetMethods();
                var genericToListMethod         = allMethodsOnEnumerableClass.Where(m => m.Name == "ToList").ToList()[0];

                var toListOfTypeOfSubProj = genericToListMethod.MakeGenericMethod(typeOfSubProj);

                MethodCallExpression toListExpression11 = Expression.Call(
                    toListOfTypeOfSubProj,
                    Expression.Constant(navigationProppertyQueryWithProjection1));

                anonymousTypeProperties.Add(new KeyValuePair <string, Type>(navigationProperty.Name, funcOfTypeOfSubProj));
                anonymousTypePropertiesValues.Add(toListExpression11);
            }

            Type projectedEntityAnonymousType = AnonymousTypeUtils.CreateType(anonymousTypeProperties);

            var constructor = projectedEntityAnonymousType.GetConstructor(anonymousTypeProperties.Select(p => p.Value).ToArray());

            var anonymousTypeInstance = Expression.New(constructor, anonymousTypePropertiesValues);

            Expression <Func <T, dynamic> > lambd11a1 = Expression.Lambda <Func <T, dynamic> >(anonymousTypeInstance, lambdaParameter);

            var projectedEntity = context.Set <T>()
                                  .AsNoTracking()
                                  .Where(e => e.Id == id)
                                  .Select(lambd11a1)
                                  .Single();

            var mainEntity = Mapper.DynamicMap <T>(projectedEntity);

            mainEntity.Id = id;

            if (selectedSelectProperties.AllProjections.NavigationPropertiesProjections.Count() > 0)
            {
                MaterializeNavigationPropertiesObsolete <T>(mainEntity, projectedEntity, projectedEntityAnonymousType, selectedSelectProperties);
            }

            var alreadytrackedentity = context.ChangeTracker.Entries <T>().Where(e => e.Entity.Id == id).SingleOrDefault();

            if (alreadytrackedentity != null)
            {
                // Remove it from tracking
                alreadytrackedentity.State = EntityState.Detached;
            }
            context.Attach(mainEntity);
            return(mainEntity);
        }
Esempio n. 24
0
        public T RetrieveObsolete <T, TResult>(int id, Expression <Func <T, TResult> > selectedProperties) where T : class, IEntity
        {
            //var arguments = selectedProperties.P.Body.
            var body = (NewExpression)selectedProperties.Body;

            List <KeyValuePair <string, Type> > projs = new List <KeyValuePair <string, Type> >();
            List <Expression> exprs = new List <Expression>();

            object navigationProppertyQueryWithProjection1 = null;
            ParameterExpression pe = Expression.Parameter(typeof(T), "p");
            Type typeOfSubProj     = null;

            foreach (var arg in body.Arguments)
            {
                if (arg.NodeType == ExpressionType.MemberAccess)
                {
                    var body1 = arg as MemberExpression;

                    var propertyInfo      = (PropertyInfo)body1.Member;
                    var nameOfTheProperty = propertyInfo.Name;
                    var typeOfTheProperty = propertyInfo.PropertyType;

                    var memberAccess1 = Expression.Property(pe, nameOfTheProperty);
                    exprs.Add(memberAccess1);

                    projs.Add(new KeyValuePair <string, Type>(nameOfTheProperty, typeOfTheProperty));
                }

                if (arg.NodeType == ExpressionType.Call)
                {
                    // Navigation property found
                    MethodCallExpression navProp = arg as MethodCallExpression;

                    var navigationProperty = navProp.Arguments[0] as MemberExpression;

                    var propertyInfo = (PropertyInfo)navigationProperty.Member;

                    var propertyType = propertyInfo.PropertyType;
                    var propertyName = propertyInfo.Name;

                    var navPropType = propertyType.GetGenericArguments()[0];

                    var generic       = typeof(Queryable).GetMethods().Where(m => m.Name == "AsQueryable").ToList()[0];
                    var genericMetgid = generic.MakeGenericMethod(navPropType);

                    ParameterExpression pe1 = Expression.Parameter(navPropType, "pre");

                    Expression left  = Expression.PropertyOrField(pe1, "MeetingId"); // TODO, get the reference based on information from  model
                    Expression right = Expression.Constant(id, typeof(int?));
                    Expression e1    = Expression.Equal(left, right);

                    var constructorinfo = typeof(EntityQueryable <>).MakeGenericType(navPropType).GetConstructors()[0];

                    var  newstsy         = constructorinfo.Invoke(new[] { context.GetService <IEntityQueryProvider>() });
                    Type func11          = typeof(EntityQueryable <>);
                    Type generic23233    = func11.MakeGenericType(navPropType);
                    var  nwtwDynamically = Expression.Constant(newstsy, generic23233);

                    Type func1111       = typeof(IQueryable <>);
                    Type generic2323311 = func1111.MakeGenericType(navPropType);

                    Type func11111        = typeof(Func <,>);
                    Type generic232331123 = func11111.MakeGenericType(navPropType, typeof(bool));
                    Type funxs            = typeof(Expression <>);
                    Type skljslk          = funxs.MakeGenericType(generic232331123);

                    var m1 = GetGenericMethod(typeof(Queryable), "Where", new[] { navPropType }, generic2323311, skljslk);

                    MethodCallExpression whereCallExpression = Expression.Call(
                        m1,
                        nwtwDynamically,     //nwtw
                        Expression.Lambda(e1, new ParameterExpression[] { pe1 }));

                    //////////////////////////////////////////////////////////

                    var jan11 = new List <KeyValuePair <string, Type> >();
                    ParameterExpression     peeee  = Expression.Parameter(navPropType, "p1");
                    List <MemberExpression> exprs1 = new List <MemberExpression>();
                    foreach (var hhhhh in navProp.Arguments.Skip(1))
                    {
                        var navigationPropertyProjection = hhhhh as LambdaExpression;

                        var body1111 = navigationPropertyProjection.Body as MemberExpression;

                        var propertyInfo11111   = (PropertyInfo)body1111.Member;
                        var nameOfTheProperty11 = propertyInfo11111.Name;
                        var typeOfTheProperty11 = propertyInfo11111.PropertyType;

                        var memberAccess1 = Expression.Property(peeee, nameOfTheProperty11);
                        exprs1.Add(memberAccess1);

                        var jan = new KeyValuePair <string, Type>(nameOfTheProperty11, typeOfTheProperty11);
                        jan11.Add(jan);
                    }

                    var annnontype11 = AnonymousTypeUtils.CreateType(jan11);

                    var constructor11 = annnontype11.GetConstructor(jan11.Select(kv => kv.Value).ToArray());
                    typeOfSubProj = constructor11.ReflectedType;
                    var genericSelectMethod = typeof(Queryable).GetMethods().Where(m => m.Name == "Select").ToList()[0];
                    var selectMetgid        = genericSelectMethod.MakeGenericMethod(navPropType, typeOfSubProj);

                    var kkkkk1 = Expression.New(constructor11, exprs1);

                    var lambd11a = Expression.Lambda(kkkkk1, peeee);

                    MethodCallExpression selctCallExpression = Expression.Call(
                        selectMetgid,
                        whereCallExpression,
                        lambd11a);

                    var provider      = ((IQueryable)context.Set <Post>()).Provider;
                    var theMethods    = typeof(IQueryProvider).GetMethods();
                    var createQMethd  = theMethods.Where(name => name.Name == "CreateQuery").ToList()[1];
                    var speciifMethod = createQMethd.MakeGenericMethod(constructor11.ReflectedType);

                    Type func        = typeof(IEnumerable <>);
                    Type generic2323 = func.MakeGenericType(typeOfSubProj);

                    projs.Add(new KeyValuePair <string, Type>(propertyName, generic2323));

                    navigationProppertyQueryWithProjection1 = speciifMethod.Invoke(provider, new object[] { selctCallExpression });
                }
            }

            var annnontype = AnonymousTypeUtils.CreateType(projs);

            var constructor = annnontype.GetConstructor(projs.Select(kv => kv.Value).ToArray());

            var tt   = typeof(Enumerable).GetMethods();
            var m133 = tt.Where(m => m.Name == "ToList").ToList()[0];
            var genericMetgid2222 = m133.MakeGenericMethod(typeOfSubProj);

            MethodCallExpression toListExpression11 = Expression.Call(
                genericMetgid2222,
                Expression.Constant(navigationProppertyQueryWithProjection1));

            exprs.Add(toListExpression11);

            var kkkkk = Expression.New(constructor, exprs);

            Expression <Func <T, dynamic> > lambd11a1 = Expression.Lambda <Func <T, dynamic> >(kkkkk, pe);

            var entiry22 = context.Set <T>().AsNoTracking().
                           Where(e => e.Id == id).
                           Select(lambd11a1).
                           Single();

            //var rrr = entiry444.
            //    Select(selectors[0]).
            //    Single();

            //var entiry = context.Set<T>().AsNoTracking().
            //    //Include(selectedProperties).
            //    Where(e => e.Id == id).
            //    Select(selectedProperties).
            //    Single();

            var retEntity = Mapper.DynamicMap <T>(entiry22);

            retEntity.Id = id;
            var alreadytrackedentity = context.ChangeTracker.Entries <T>().Where(e => e.Entity.Id == id).SingleOrDefault();

            if (alreadytrackedentity != null)
            {
                // Remove it from tracking
                alreadytrackedentity.State = EntityState.Detached;
            }
            context.Attach(retEntity);
            return(retEntity);
        }