将表达式分配给表达式树内的属性

时间:2015-04-01 08:49:36

标签: c# linq entity-framework lambda expression

有没有办法将选择器表达式的“结果”赋值给表达式树中另一个选择器的属性?

澄清一下:我想使用选择器表达式将从数据库检索到的结果集转换为数据传输对象。我的例子通常看起来像这样:

Expression<Func<Parent, ParentDto>> selector = parent =>
new ParentDto {
    Children = parent.Children.Select(x => new ChildDto())...

然而,这不适用于 Linq To Entities ,因为Children(实体Parent上的属性)只是IEnumerable<T> ,没有初始值设定项< / strong>即可。对于这种情况,我有一个静态表达式访问器public static Expression<Func<Parent, ICollection<Child>>> ChildrenAccessor = f => f.InternalChildrenStorage),它返回内部集合(ICollection<T>)。现在我需要:

  1. 为子实体创建dto映射表达式
  2. 为父实体(父实体)创建dto映射表达式
  3. 将静态存取器的参数替换为子实体映射表达式
  4. 中的参数
  5. 将父映射表达式与子实体映射表达式
  6. 组合

    最后,它应该(伪)是这样的:

    Expression<Func<Parent, ParentDto>> selector = parent =>
        new ParentDto {
            Children = parent.InternalChildrenStorage.Select(x => new ChildDto())...
    

    这是我得到的(真实世界代码):

    // Parent = SetupGroup
    // Child  = SetupMap
    
    Expression<Func<ICollection<SetupMap>, IEnumerable<SetupMapDto>>> transformMapsToDto =
            maps => maps.Select(x => new SetupMapDto
            {
                Camera = new SetupMapCameraDto
                {
                    Id = x.Camera.Id,
                    FriendlyName = x.Camera.FriendlyName
                },
                Display = new SetupMapDisplayDto
                {
                    Id = x.Display.Id,
                    FriendlyName = x.Display.FriendlyName
                }
            }).Where(x => x.Camera != null);
    var mapsSelector = SetupGroup.SetupMapsAccessor.Combine(transformMapsToDto);
        Expression<Func<SetupGroup, SetupGroupReportDto>> transformGroupsToDto = @group 
            => new SetupGroupReportDto {
                GroupText   = @group.GroupText,
                GroupNumber = @group.GroupNumber
            };
    
    Expression<Func<SetupGroupReportDto, IEnumerable<SetupMapDto>>> dtoMapsSelector = dto => dto.SetupMaps;
    var parameterExpression = (ParameterExpression) (((MemberExpression) (dtoMapsSelector.Body)).Expression);
    var assignment = Expression.Lambda<Action<SetupGroupReportDto>>(Expression.Assign(dtoMapsSelector.Body, mapsSelector.Body),
                        parameterExpression);
    
    var resultDtoBlock      = Expression.Block(transformGroupsToDto, assignment);
    
    var selectorParameter   = Expression.Parameter(typeof (SetupGroup));
    var dtoSelector         = Expression.Lambda<Func<SetupGroup, SetupGroupReportDto>>(resultDtoBlock, selectorParameter);
    
    var results = _setupGroupRepository.GetAll(dtoSelector);
    

    这似乎不起作用,因为块表达式的第二部分(赋值)没有与transformGroupsToDto表达式结合。我是否误解了Expression.Block的目的?

0 个答案:

没有答案