public static IQueryable SelectByInterface <T>(this IQueryable <T> source, Type interfaceType, bool includeTypeName = true)
        {
            var properties = interfaceType.GetPublicProperties().Where(each => each.PropertyType.IsSimple()).ToList();

            var objectFields = properties.Select(each => each.Name).ToList();

            if (includeTypeName)
            {
                objectFields.Add("_Type");
            }

            var sourceType = source.GetType().GetGenericArguments().First();

            var param       = Expression.Parameter(sourceType);
            var expressions = new List <MemberBinding>();

            lock (RuntimeTypes) {
                if (!RuntimeTypes.ContainsKey(interfaceType))
                {
                    var runtimeType = new RuntimeObjectBuilder().CreateNewObject(interfaceType, interfaceType, objectFields.ToArray()).GetType();
                    RuntimeTypes.Add(interfaceType, runtimeType);
                }

                var instance = Activator.CreateInstance(RuntimeTypes[interfaceType]);
                var type     = instance.GetType();

                if (includeTypeName)
                {
                    var typeProperty = type.GetProperty("_Type");
                    expressions.Add(Expression.Bind(typeProperty, Expression.Constant(typeof(T).Name)));
                }

                foreach (var property in instance.GetType().GetProperties())
                {
                    if (property.Name.StartsWith("_"))
                    {
                        continue;
                    }

                    expressions.Add(Expression.Bind(property, Expression.PropertyOrField(param, property.Name)));
                }

                var init = Expression.MemberInit(Expression.New(instance.GetType()), expressions.ToArray());

                var func          = typeof(Func <,>).MakeGenericType(typeof(T), type);
                var lambdaMethods = typeof(Expression).GetMethods().Where(each => each.Name == "Lambda");

                var expression = lambdaMethods.First().MakeGenericMethod(func).Invoke(null, new object[] { init, new[] { param } }) as Expression;

                //var expression = Expression.Lambda<Func<T, I>>(init, param);
                var methods = typeof(Queryable).GetMethods().Where(each => each.Name == "Select").ToList();
                var method  = methods.FirstOrDefault().MakeGenericMethod(typeof(T), type);

                return(method.Invoke(null, new object[] { source, expression }) as IQueryable);
            }
        }
        public static IQueryable <BaseRuntimeObject> DynamicSelect <T, G>(this IQueryable <IGrouping <G, T> > source, string groupName, params string[] propertyNames)
        {
            var objectFields = new List <string>(propertyNames);

            objectFields.Add(groupName);

            var sourceType = source.GetType().GetGenericArguments().First();

            var param         = Expression.Parameter(sourceType);
            var expressions   = new List <MemberBinding>();
            var instance      = new RuntimeObjectBuilder().CreateNewObject(typeof(T), null, objectFields.ToArray());
            var type          = instance.GetType();
            var groupProperty = type.GetProperty(groupName);

            foreach (var propertyName in propertyNames)
            {
                var property = type.GetProperty(propertyName);

                var sumMethod = typeof(Enumerable).GetMethods()
                                .FirstOrDefault(x => x.Name == "Sum" && x.ContainsGenericParameters && x.ReturnType == property.PropertyType);

                if (sumMethod != null)
                {
                    var eachEntity     = Expression.Parameter(typeof(T), "each");
                    var propertyAccess = Expression.Property(eachEntity, propertyName);

                    var lambda = Expression.Lambda(propertyAccess, eachEntity);

                    var sumExpression = Expression.Call(sumMethod.MakeGenericMethod(typeof(T)), param, lambda);

                    expressions.Add(Expression.Bind(property, sumExpression));
                }
                else
                {
                    expressions.Add(Expression.Bind(property, Expression.PropertyOrField(param, propertyName)));
                }
            }

            expressions.Add(Expression.Bind(groupProperty, Expression.PropertyOrField(param, "Key")));

            var init = Expression.MemberInit(Expression.New(instance.GetType()), expressions.ToArray());

            var expression = Expression.Lambda <Func <IGrouping <G, T>, BaseRuntimeObject> >(init, param);

            return(source.Select(expression));
        }