public virtual EntityViewer GetViewer <TEntity>() where TEntity : class, IEntity, new() { IEntityQueryable <TEntity> context = EntityBuilder.GetContext <TEntity>(); EntityMetadata metadata = EntityAnalyzer.GetMetadata <TEntity>(); EntityViewModel <TEntity> model = new EntityViewModel <TEntity>(context.OrderBy()); model.Headers = metadata.ViewProperties; model.UpdateItems(); EntityViewer viewer = new EntityViewer(this); viewer.Model = model; WpfViewButton createButton = new WpfViewButton(); createButton.Name = "Create"; createButton.Command = new EntityCommand(new EntityCommand.ExecuteDelegate(t => { viewer.NavigationService.Navigate(GetEditor <TEntity>(context.Create())); })); model.Buttons = new EntityViewButton[] { createButton }; return(viewer); }
/// <summary> /// Initialize entity controller. /// </summary> /// <param name="builder">Context builder of entity.</param> public EntityController(IEntityContextBuilder builder) : base(builder) { EntityQueryable = EntityBuilder.GetContext <TEntity>(); Metadata = EntityAnalyzer.GetMetadata <TEntity>(); PageSize = EntityViewModel.DefaultPageSizeOption; }
/// <summary> /// Initialize entity edit model. /// </summary> /// <param name="entity">Entity to edit.</param> public EntityEditModel(TEntity entity) { Item = entity; Metadata = EntityAnalyzer.GetMetadata <TEntity>(); //Let repository library to set Properties value. //Don't: Properties = Metadata.EditProperties; }
/// <summary> /// Initialize entity controller. /// </summary> /// <param name="builder">Context builder of entity.</param> public EntityController(IEntityContextBuilder builder) : base(builder) { EntityQueryable = EntityContext = EntityBuilder.GetContext <TEntity>(); Metadata = EntityAnalyzer.GetMetadata <TEntity>(); PageSize = Pagination.DefaultPageSizeOption; Untils = new EntityControllerUnitils <TEntity>(this, builder); Untils.PageSize = PageSize; }
public ServiceEntityQueryable(IEntityService <TEntity> service) { if (service == null) { throw new ArgumentNullException("service"); } _Service = service; Metadata = EntityAnalyzer.GetMetadata <TEntity>(); }
public EntityController(IEntityContextBuilder builder) { if (builder == null) { throw new ArgumentNullException("builder"); } EntityBuilder = builder; EntityQueryable = EntityBuilder.GetContext <TEntity>(); Metadata = EntityAnalyzer.GetMetadata <TEntity>(); }
/// <summary> /// Initialize entity queryable context. /// </summary> /// <param name="dbContext">Database context of entity framework.</param> public EntityQueryable(DbContext dbContext) { DbContext = dbContext; var dbset = DbContext.GetType().GetProperties().FirstOrDefault(t => t.PropertyType == typeof(DbSet <TEntity>)); if (dbset == null) { throw new ArgumentException("dbContext不包含DbSet<" + typeof(TEntity).Name + ">"); } DbSet = (DbSet <TEntity>)dbset.GetValue(DbContext, null); Metadata = EntityAnalyzer.GetMetadata <TEntity>(); }
public virtual EntityEditor GetEditor <TEntity>(TEntity entity) where TEntity : class, IEntity, new() { EntityMetadata metadata = EntityAnalyzer.GetMetadata <TEntity>(); EntityEditModel <TEntity> model = new EntityEditModel <TEntity>(entity); model.Properties = metadata.EditProperties; EntityEditor editor = new EntityEditor(this); editor.Model = model; return(editor); }
/// <summary> /// Return a string that entity display. /// </summary> /// <returns></returns> public override string ToString() { var metadata = EntityAnalyzer.GetMetadata(GetType()); if (metadata.DisplayProperty == null) { return(base.ToString()); } object value = metadata.DisplayProperty.GetValue(this); if (value == null) { return(""); } else { return(value.ToString()); } }
/// <summary> /// Called when authorization is required. /// </summary> /// <param name="filterContext">The filter context.</param> public void OnAuthorization(AuthorizationContext filterContext) { if (filterContext.Controller is EntityController) { EntityBuilder = ((EntityController)filterContext.Controller).EntityBuilder; } else { return; } if (filterContext.Controller.GetType().IsGenericType) { Metadata = EntityAnalyzer.GetMetadata(filterContext.Controller.GetType().GetGenericArguments()[0]); } RouteData = filterContext.RouteData; if (!Authorize(filterContext)) { filterContext.Result = new HttpStatusCodeResult(403); } }
//private ReadOnlyCollection<ValidationResult> _NoError = new ReadOnlyCollection<ValidationResult>(new List<ValidationResult>()); /// <summary> /// Ensure that entity is valid. /// </summary> /// <param name="validationContext">Validation context.</param> /// <returns>Collection that include error messages.</returns> public IEnumerable <ValidationResult> Validate(ValidationContext validationContext) { var metadata = EntityAnalyzer.GetMetadata(GetType()); var result = new List <ValidationResult>(); foreach (var property in metadata.Properties) { validationContext.MemberName = property.ClrName; validationContext.DisplayName = property.Name; var list = property.GetAttributes <ValidationAttribute>(); foreach (var item in list) { var r = item.GetValidationResult(property.GetValue(this), validationContext); if (r != null && r != ValidationResult.Success) { result.Add(r); } } } return(result); }
async void _Add_Click(object sender, RoutedEventArgs e) { dynamic controller = EntityRouter.Routers.GetController(EntityAnalyzer.GetMetadata(Metadata.ClrType.GetGenericArguments()[0])); EntityMultipleSelector selector = (EntityMultipleSelector)await controller.GetMultipleSelector(); if (selector.ShowDialog() == true) { var items = selector.SelectedEntity.Except(_CurrentList).ToArray(); foreach (var item in items) { if (_OriginList.Contains(item)) { _RemoveList.Remove(item); } else { _AddList.Add(item); } _CurrentList.Add(item); } } }
/// <summary> /// Initialize entity view model. /// </summary> /// <param name="queryable">Queryable of entity.</param> /// <param name="page">Current page.</param> /// <param name="size">Current page size.</param> public EntityViewModel(IQueryable <TEntity> queryable, int page, int size) { if (queryable == null) { throw new ArgumentNullException("queryable"); } if (page < 1) { throw new ArgumentException("Can not less than 1.", "page"); } if (size < 1) { throw new ArgumentException("Can not less than 1.", "size"); } ViewButtons = new IViewButton[0]; ItemButtons = new IEntityViewButton[0]; CurrentSize = size; PageSizeOption = Pagination.DefaultPageSizeOption; Metadata = EntityAnalyzer.GetMetadata <TEntity>(); Queryable = queryable; UpdateTotalPage(); SetPage(page); }
private async Task GetParentModel(List <EntityParentModel> root, Dictionary <Guid, EntityParentModel[]> items, IEntityMetadata metadata, Guid?selected, string path) { IEntityMetadata parentMetadata = EntityAnalyzer.GetMetadata(metadata.ParentProperty.ClrType); dynamic context = EntityBuilder.GetContext(parentMetadata.Type); dynamic queryable = context.OrderBy(); if (parentMetadata.ParentProperty == null) { IEntity[] result = await context.ToArrayAsync(queryable); foreach (var item in result) { EntityParentModel model = new EntityParentModel(); model.Index = item.Index; model.Name = item.ToString(); model.Path = path; model.IsSelected = selected == item.Index; if (items.ContainsKey(model.Index)) { model.Items = items[model.Index]; } else { model.Items = new EntityParentModel[0]; } root.Add(model); } } else { Dictionary <Guid, EntityParentModel[]> newItems = new Dictionary <Guid, EntityParentModel[]>(); var parameter = Expression.Parameter(parentMetadata.Type); var parent = Expression.Property(parameter, parentMetadata.ParentProperty.ClrName); var expression = Expression.Lambda(parent, parameter); dynamic result = GetGrouping(queryable, parentMetadata.ParentProperty.ClrType, parentMetadata.Type, expression); List <EntityParentModel> thisRoot = null; if (parentMetadata.ParentProperty.ClrType == parentMetadata.Type) { thisRoot = new List <EntityParentModel>(); } Type groupType = typeof(IGrouping <,>).MakeGenericType(parentMetadata.ParentProperty.ClrType, parentMetadata.Type); foreach (dynamic item in result) { List <EntityParentModel> models = new List <EntityParentModel>(); IEntity key = groupType.GetProperty("Key").GetValue(item) as IEntity; foreach (IEntity entity in item) { EntityParentModel model = new EntityParentModel(); model.Index = entity.Index; model.Name = entity.ToString(); model.Path = path; model.IsSelected = selected == entity.Index; if (items.ContainsKey(model.Index)) { model.Items = items[model.Index]; } else { model.Items = new EntityParentModel[0]; } models.Add(model); } if (key == null) { root.AddRange(models); if (parentMetadata.ParentProperty.ClrType == parentMetadata.Type) { thisRoot.AddRange(models); } } else { newItems.Add(key.Index, models.ToArray()); } } if (parentMetadata.ParentProperty.ClrType == parentMetadata.Type) { ExpendTree(thisRoot, newItems); } else { await GetParentModel(root, newItems, parentMetadata, selected, path + "." + parentMetadata.ParentProperty.ClrName); } } }
/// <summary> /// Get search item in request. /// </summary> /// <param name="queryable">Queryable of TEntity.</param> /// <returns>Search item of TEntity.</returns> public EntitySearchItem[] GetSearchItem(ref IQueryable <TEntity> queryable) { List <EntitySearchItem> searchItems = new List <EntitySearchItem>(); var keys = Controller.Request.QueryString.AllKeys.Where(t => t.StartsWith("Search.")).Select(t => t.Substring(7).Split('.')).GroupBy(t => t[0], t => t.Length == 1 ? "" : "." + t[1]).ToArray(); for (int i = 0; i < keys.Length; i++) { string propertyName = keys[i].Key; IPropertyMetadata property = Metadata.GetProperty(propertyName); if (property == null || !property.Searchable) { continue; } EntitySearchItem searchItem = new EntitySearchItem(); string[] options = keys[i].ToArray(); switch (property.Type) { case ComponentModel.DataAnnotations.CustomDataType.Date: case ComponentModel.DataAnnotations.CustomDataType.DateTime: for (int a = 0; a < options.Length; a++) { if (options[a] == ".Start") { DateTime start; if (!DateTime.TryParse(Controller.Request.QueryString["Search." + keys[i].Key + options[a]], out start)) { continue; } searchItem.MorethanDate = start; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.GreaterThanOrEqual(Expression.Property(parameter, property.ClrName), Expression.Constant(start)), parameter)); } else if (options[a] == ".End") { DateTime end; if (!DateTime.TryParse(Controller.Request.QueryString["Search." + keys[i].Key + options[a]], out end)) { continue; } if (property.Type == CustomDataType.Date) { end = end.AddDays(1); } searchItem.LessthanDate = end; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.LessThanOrEqual(Expression.Property(parameter, property.ClrName), Expression.Constant(end)), parameter)); } } break; case ComponentModel.DataAnnotations.CustomDataType.Boolean: case ComponentModel.DataAnnotations.CustomDataType.Sex: if (options[0] == "") { bool result; if (!bool.TryParse(Controller.Request.QueryString["Search." + keys[i].Key], out result)) { continue; } searchItem.Equal = result; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.Equal(Expression.Property(parameter, property.ClrName), Expression.Constant(result)), parameter)); } break; case ComponentModel.DataAnnotations.CustomDataType.Currency: case ComponentModel.DataAnnotations.CustomDataType.Integer: case ComponentModel.DataAnnotations.CustomDataType.Number: for (int a = 0; a < options.Length; a++) { if (options[a] == ".Start") { double start; if (!double.TryParse(Controller.Request.QueryString["Search." + keys[i].Key + options[a]], out start)) { continue; } searchItem.Morethan = start; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.GreaterThanOrEqual(Expression.Property(parameter, property.ClrName), Expression.Constant(start)), parameter)); } else if (options[a] == ".End") { double end; if (!double.TryParse(Controller.Request.QueryString["Search." + keys[i].Key + options[a]], out end)) { continue; } searchItem.Lessthan = end; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.LessThanOrEqual(Expression.Property(parameter, property.ClrName), Expression.Constant(end)), parameter)); } } break; case ComponentModel.DataAnnotations.CustomDataType.Other: if (property.CustomType == "Enum") { object result; try { result = Enum.Parse(property.ClrType, Controller.Request.QueryString["Search." + keys[i].Key]); } catch { continue; } searchItem.Enum = new EnumConverter(property.ClrType).ConvertToString(result); ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.Equal(Expression.Property(parameter, property.ClrName), Expression.Constant(result)), parameter)); } else if (property.CustomType == "Entity") { searchItem.Contains = Controller.Request.QueryString["Search." + keys[i].Key]; ParameterExpression parameter = Expression.Parameter(Metadata.Type); Expression expression = Expression.Property(Expression.Property(parameter, property.ClrName), EntityAnalyzer.GetMetadata(property.ClrType).DisplayProperty.ClrName); expression = Expression.Call(expression, typeof(string).GetMethod("Contains"), Expression.Constant(searchItem.Contains)); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(expression, parameter)); } break; default: if (property.ClrType == typeof(string)) { searchItem.Contains = Controller.Request.QueryString["Search." + keys[i].Key]; ParameterExpression parameter = Expression.Parameter(Metadata.Type); Expression expression = Expression.Property(parameter, property.ClrName); expression = Expression.Call(expression, typeof(string).GetMethod("Contains"), Expression.Constant(searchItem.Contains)); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(expression, parameter)); } break; } if (searchItem.Contains != null || searchItem.Enum != null || searchItem.Equal.HasValue || searchItem.Lessthan.HasValue || searchItem.LessthanDate.HasValue || searchItem.Morethan.HasValue || searchItem.MorethanDate.HasValue) { searchItem.Name = property.Name; } if (searchItem.Name != null) { searchItems.Add(searchItem); } } return(searchItems.ToArray()); }
/// <summary> /// Initialize entity. /// </summary> public EntityBase() { _Metadata = EntityAnalyzer.GetMetadata(this.GetType()); }
public virtual ActionResult Index(int page = 1, int size = 20, string parentpath = null, Guid?parentid = null, bool search = false) { if (page < 1) { return(new HttpStatusCodeResult(400)); } if (size < 1) { return(new HttpStatusCodeResult(400)); } if (!Metadata.ViewRoles.All(t => User.IsInRole(t))) { return(new HttpStatusCodeResult(403)); } IQueryable <TEntity> queryable = EntityQueryable.Query(); List <EntitySearchItem> searchItems = new List <EntitySearchItem>(); if (search) { var keys = Request.QueryString.AllKeys.Where(t => t.StartsWith("Search.")).Select(t => t.Substring(7).Split('.')).GroupBy(t => t[0], t => t.Length == 1 ? "" : "." + t[1]).ToArray(); for (int i = 0; i < keys.Length; i++) { string propertyName = keys[i].Key; PropertyMetadata property = Metadata.GetProperty(propertyName); if (property == null || !property.Searchable) { continue; } EntitySearchItem searchItem = new EntitySearchItem(); string[] options = keys[i].ToArray(); switch (property.Type) { case ComponentModel.DataAnnotations.CustomDataType.Date: case ComponentModel.DataAnnotations.CustomDataType.DateTime: for (int a = 0; a < options.Length; a++) { if (options[a] == ".Start") { DateTime start; if (!DateTime.TryParse(Request.QueryString["Search." + keys[i].Key + options[a]], out start)) { continue; } searchItem.MorethanDate = start; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.GreaterThanOrEqual(Expression.Property(parameter, property.Property), Expression.Constant(start)), parameter)); } else if (options[a] == ".End") { DateTime end; if (!DateTime.TryParse(Request.QueryString["Search." + keys[i].Key + options[a]], out end)) { continue; } searchItem.LessthanDate = end; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.LessThanOrEqual(Expression.Property(parameter, property.Property), Expression.Constant(end)), parameter)); } } break; case ComponentModel.DataAnnotations.CustomDataType.Boolean: case ComponentModel.DataAnnotations.CustomDataType.Sex: if (options[0] == "") { bool result; if (!bool.TryParse(Request.QueryString["Search." + keys[i].Key], out result)) { continue; } searchItem.Equal = result; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.Equal(Expression.Property(parameter, property.Property), Expression.Constant(result)), parameter)); } break; case ComponentModel.DataAnnotations.CustomDataType.Currency: case ComponentModel.DataAnnotations.CustomDataType.Integer: case ComponentModel.DataAnnotations.CustomDataType.Number: for (int a = 0; a < options.Length; a++) { if (options[a] == ".Start") { double start; if (!double.TryParse(Request.QueryString["Search." + keys[i].Key + options[a]], out start)) { continue; } searchItem.Morethan = start; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.GreaterThanOrEqual(Expression.Property(parameter, property.Property), Expression.Constant(start)), parameter)); } else if (options[a] == ".End") { double end; if (!double.TryParse(Request.QueryString["Search." + keys[i].Key + options[a]], out end)) { continue; } searchItem.Lessthan = end; ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.LessThanOrEqual(Expression.Property(parameter, property.Property), Expression.Constant(end)), parameter)); } } break; case ComponentModel.DataAnnotations.CustomDataType.Other: if (property.CustomType == "Enum") { object result; try { result = Enum.Parse(property.Property.PropertyType, Request.QueryString["Search." + keys[i].Key]); } catch { continue; } searchItem.Enum = new EnumConverter(property.Property.PropertyType).ConvertToString(result); ParameterExpression parameter = Expression.Parameter(Metadata.Type); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(Expression.Equal(Expression.Property(parameter, property.Property), Expression.Constant(result)), parameter)); } else if (property.CustomType == "Entity") { searchItem.Contains = Request.QueryString["Search." + keys[i].Key]; ParameterExpression parameter = Expression.Parameter(Metadata.Type); Expression expression = Expression.Property(Expression.Property(parameter, property.Property), EntityAnalyzer.GetMetadata(property.Property.PropertyType).DisplayProperty.Property); expression = Expression.Call(expression, typeof(string).GetMethod("Contains"), Expression.Constant(searchItem.Contains)); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(expression, parameter)); } break; default: if (property.Property.PropertyType == typeof(string)) { searchItem.Contains = Request.QueryString["Search." + keys[i].Key]; ParameterExpression parameter = Expression.Parameter(Metadata.Type); Expression expression = Expression.Property(parameter, property.Property); expression = Expression.Call(expression, typeof(string).GetMethod("Contains"), Expression.Constant(searchItem.Contains)); queryable = queryable.Where <TEntity>(Expression.Lambda <Func <TEntity, bool> >(expression, parameter)); } break; } if (searchItem.Contains != null || searchItem.Enum != null || searchItem.Equal.HasValue || searchItem.Lessthan.HasValue || searchItem.LessthanDate.HasValue || searchItem.Morethan.HasValue || searchItem.MorethanDate.HasValue) { searchItem.Name = property.Name; } if (searchItem.Name != null) { searchItems.Add(searchItem); } } } else { if (parentpath != null && parentid.HasValue) { try { queryable = EntityQueryable.InParent(queryable, parentpath, parentid.Value); } catch { return(new HttpStatusCodeResult(400)); } } } var model = new EntityViewModel <TEntity>(EntityQueryable.OrderBy(queryable), page, size); if (Metadata.ParentProperty != null && !search) { model.Parent = GetParentModel(parentid, Metadata.ParentLevel); } model.SearchItem = searchItems.ToArray(); model.Headers = Metadata.ViewProperties; model.PageSizeOption = PageSize; model.UpdateItems(); return(View(model)); }
protected EntityServiceClient() { Metadata = EntityAnalyzer.GetMetadata <TEntity>(); }
private EntityParentModel[] GetParentModel(Guid?selected, int level) { EntityMetadata metadata = Metadata; List <EntityParentModel> final = new List <EntityParentModel>(); ParameterExpression parameter = Expression.Parameter(Metadata.Type); //获取Parent属性组 dynamic fl = GetGrouping(EntityQueryable.Query(), metadata.ParentProperty.Property.PropertyType, metadata.Type, GetLambda(metadata.Type, metadata.ParentProperty.Property.PropertyType, Expression.Property(parameter, Metadata.ParentProperty.Property), parameter)); string path = metadata.ParentProperty.Property.Name; List <EntityParentModel> parents = null; while (parents == null || parents.Count > 0) { if (parents == null) { parents = new List <EntityParentModel>(); } List <EntityParentModel> temp = new List <EntityParentModel>(); foreach (var f in fl) { Type ft = f.GetType(); IEntity entity = ft.GetProperty("Key").GetValue(f); if (entity == null) { continue; } EntityParentModel item = final.SingleOrDefault(t => t.Index == entity.Index); if (item == null) { item = new EntityParentModel(); item.Path = path; item.Name = entity.ToString(); item.Index = entity.Index; } if (selected.HasValue && item.Index == selected) { item.Selected = true; } //ParameterExpression dp = Expression.Parameter(metadata.Type); //dynamic dChildren = _ESelectMethod.MakeGenericMethod(metadata.Type, typeof(Guid)).Invoke(null, new object[] { f, GetLambda(metadata.Type, typeof(Guid), Expression.Property(dp, typeof(EntityBase).GetProperty("BaseIndex")), dp) }); dynamic dChildren = _ESelectMethod.MakeGenericMethod(metadata.Type, typeof(Guid)).Invoke(null, new object[] { f, new Func <IEntity, Guid>(GetBaseIndex) }); Guid[] children = Linq.Enumerable.ToArray <Guid>(dChildren); if (item.Items != null) { item.Items = item.Items.Concat(parents.Where(t => children.Contains(t.Index))).ToArray(); } else { item.Items = parents.Where(t => children.Contains(t.Index)).ToArray(); } if (!item.Selected && item.Items.Count(t => t.Selected) > 0) { item.Opened = true; } parents.RemoveAll(t => children.Contains(t.Index)); temp.Add(item); } final.AddRange(parents); parents = temp; Type groupType = typeof(IGrouping <,>).MakeGenericType(metadata.ParentProperty.Property.PropertyType, metadata.Type); metadata = EntityAnalyzer.GetMetadata(metadata.ParentProperty.Property.PropertyType); if (metadata.ParentProperty == null || parents.Count == 0) { final.AddRange(parents); break; } level--; if (level == 0) { final.AddRange(parents); break; } path += "." + metadata.ParentProperty.Property.Name; parameter = Expression.Parameter(groupType); var selectKey = GetLambda(groupType, metadata.Type, Expression.Property(parameter, groupType.GetProperty("Key")), parameter); parameter = Expression.Parameter(metadata.Type); fl = _QSelectMethod.MakeGenericMethod(groupType, metadata.Type).Invoke(null, new object[] { fl, selectKey }); var groupByKey = GetLambda(metadata.Type, metadata.ParentProperty.Property.PropertyType, Expression.Property(parameter, metadata.ParentProperty.Property), parameter); fl = GetGrouping(fl, metadata.ParentProperty.Property.PropertyType, metadata.Type, groupByKey); } return(final.ToArray()); }