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); }
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); }
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); }