Expression-tree to build sub-select results

2019-08-18 04:36发布

问题:

I'm trying to build a sub-query by using expression-trees. In linq I would write something like:

var single = MyTable
    .AsExpandable()
    .Select(c => new
    {
        Childs = Enumerable.Select(
            MyTable.VisibleChilds.Invoke(c, dbContext),
            cc => Convert(cfg.ChildsConfig).Invoke(dbContext, cc))
    });

where the Convert is building an expression like

p => new MyTableSelect {
    Id = p.Id,
    Name = p.Name
}

depending on the given values from the config (to only read needed data from database).

but I'm struggeling with the second parameter to be passed to the Select call as I need cc to be passed to the Convert-call.

I guess I need something like Expression.Lambda<Func<>> but I don't see it.

Expression.Lambda>(Expression.Invoke(Instance.Convert(cfg.ChildOrganizersFilterConfig), ContextParameter, theEntity));

回答1:

I am not familiar with your use of Invoke but if you just want to run a 'Converter' in a fluent syntax for use in a Linq Expression I could show you an example of that. Say I have three POCO classes, one parent container, a child container, and a container I want to convert to.

public class POC
{
    public int Id { get; set; }
    public string Name { get; set; }

    public POC(int id, string name)
    {
      Id = id;
      Name = name;
    }
}

public class ChildPOC
{
    public int ParentId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public ChildPOC(int parentId, string firstName, string lastName)
    {
      ParentId = parentId;
      FirstName = firstName;
      LastName = lastName;
    }
}
public class ChildPOCAlter
{
    public int ParentId { get; set; }
    public string Name { get; set; }

    public ChildPOCAlter(string first, string last, int parentId)
    {
      ParentId = parentId;
      Name = $"{first} {last}";
    }
}

I could write a converter method to take ChildPOC to ChildPOCAlter like so:

public static Converter<ChildPOC, ChildPOCAlter> ChildPOCOAlter()
{
  return new Converter<ChildPOC, ChildPOCAlter>((x) => { return new ChildPOCAlter(x.FirstName, x.LastName, x.ParentId); });
}

I could then populate some data:

var someParents = new List<POC> { new POC(1, "A"), new POC(2, "B") };
var somechildren = new List<ChildPOC> { new ChildPOC(1, "Brett", "x"), new ChildPOC(1, "Emily", "X"), new ChildPOC(2, "John", "Y") };

And then I may want to take these relationships and apply a converter directly on it:

var relationships = someParents.Select(x => new
{
    Id = x.Id,
    Name = x.Name,
    Children = somechildren.Where(y => y.ParentId == x.Id).ToList().ConvertAll(ChildPOCOAlter())
});