1

Can I create a MemberInitExpression or any expression of a parameterless constructor from a function that literally returns a parameterless constructor?

public IQueryable<GroupView> GetViewSelect(IQueryable<ItemGroup> myQ)
{
    return myQ.SelectMany(GetExpression1(), GetExpression2());
}        

internal static Expression<Func<ItemGroup, IEnumerable<ItemDetail>>> 
    GetExpression1()
{
    // m is the ItemGroup
    // m.item is Item
    // m.item.itemDetail is a collection of ItemDetail
    return m => m.item.itemDetail; 
}

internal static Expression<Func<ItemGroup, ItemDetail, GroupView>> 
    GetExpression2()
{
    // m is the ItemGroup
    // n is the ItemDetail
    // and it's error at runtime coz LINQ doesnt know the GetGroupView.. :(
    return (m, n) => GetGroupView(m, n);
}

internal static GroupView GetGroupView(ItemGroup m, ItemDetail n)
{
    // I think the same error will occurs
    // coz LINQ doesnt know the GetItemView and GetItemDetailView
    return new GroupView
    {
        Id = m.id,
        Name = m.name,
        ItemDetailsTotalCount = 
            m.item.ItemDetails.Sum(nn => nn.item.itemDetails.Count),

        Item = GetItemView(m.item),
        ItemDetail = GetItemDetailView(n)
    };
}    

internal static ItemView GetItemView(Item m)
{
    return new ItemView
    {
        Id = m.id,
        Name = m.name,
        DetailCount = m.ItemDetail.Count
    };
}

internal static ItemDetailView GetItemDetailView(ItemDetail n)
{
    return new ItemDetailView
    {
        Id = n.id,
        Name = n.name,            
        Supplier = GetSupplierView(n.supplier)
    };
}

internal static SupplierView GetSupplierView(Supplier n)
{
    return new SupplierView
    {
        Id = n.id,
        Name = n.name,
        Email = n.email ?? "no email",
        Phone = n.phone ?? "no phone"
    };
} 

Of course none of those above works,.. but I just want to avoid retyping the same parameterless constructor over and over in order to get the view constructor every time I want to get different view..

For example, I'd like to call it like this

public IQueryable<ItemView> GetViewSelect(IQueryable<Item> myQ)
{
    return myQ.Select(GetExpression3());
}        

public IQueryable<ItemView> GetViewSelect(IQueryable<ItemDetail> myQ)
{
    return myQ.Select(GetExpression3());
}        

internal static Expression<Func<Item, ItemView>> GetExpression3()
{
    return m => GetItemView(m); 
}

internal static Expression<Func<ItemDetail, ItemView>> GetExpression4()
{
    return m => GetItemView(m.item);
}

instead of writing the same parameterless constructor everytime I call it like this below..

internal static Expression<Func<Item, ItemView>> GetExpression3()
{
    // writing same parameterless constructor again
    return m => new ItemView
    {
        Id = m.id,
        Name = m.name,
        DetailCount = m.ItemDetail.Count
    }; 
}

internal static Expression<Func<ItemDetail, ItemView>> GetExpression4()
{
    // the same thing again
    return m => new ItemView
    {
        Id = m.item.id,
        Name = m.item.name,
        DetailCount = m.item.ItemDetail.Count
    };
}

internal static Expression<Func<ItemGroup, ItemDetail, GroupView>> 
    GetExpression2()
{
    return (m, n) => new GroupView
    {
        Id = m.id,
        Name = m.name,
        ItemDetailsTotalCount = 
            m.item.ItemDetails.Sum(nn => nn.item.itemDetails.Count),

        Item = new ItemView
        {
            Id = m.item.id,
            Name = m.item.name,
            DetailCount = m.item.ItemDetail.Count
        },
        ItemDetail = new ItemDetailView
        {
            Id = n.id,
            Name = n.name,            
            Supplier = new SupplierView
            {
                Id = n.id,
                Name = n.name,
                Email = n.email ?? "no email",
                Phone = n.phone ?? "no phone"
            }
        }
    };
}

So I was actually looking for a way to convert

new ItemView
{
    Id = m.id,
    Name = m.name,
    DetailCount = m.ItemDetail.Count
}

into a MemberInitExpression parameterless constructor so maybe I can use it like below without doing any member-assignment..

internal Expression<Func<Item, ItemView>> GetExpression4e
    (ParameterExpression m)
{
    // looking for something like this.. 
    MemberInitExpression ItemViewInitExpression = 
        Something("GetItemView", new Object[] {m});

    return Expression.Lambda<Func<Item, ItemView>>
        (ItemViewInitExpression, m);
}
sickdoctor
  • 85
  • 6

1 Answers1

1
internal static Expression<Func<Item, ItemView>> GetExpression3()
{
    // writing same parameterless constructor again
    return m => new ItemView
    {
        Id = m.id,
        Name = m.name,
        DetailCount = m.ItemDetail.Count
    }; 
}

This method already produces a MemberInitExpression. If you do

var type = GetExpression3().Body.GetType();

You'll get System.Linq.Expressions.MemberInitExpression

If all you want is to pass some parameters, then pass some parameters:

internal static Expression<Func<Item, ItemView>> GetExpression3(int id, string name, int count)    
{
    // writing same parameterless constructor again
    return m => new ItemView
    {
        Id = id,
        Name = name,
        DetailCount = count
    }; 
}
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • you're right sir.. I think it requires implementation of [this](http://stackoverflow.com/questions/6736505/how-to-combine-two-lambdas/6736589#6736589) to make sure the parameter is bound to the LINQ – sickdoctor Aug 19 '13 at 09:37
  • The conversion should be dynamic so it can be used in large generalized cases. i.e. the implementation followed is not. You should use the real power of LINQ expression – AbuDawood Nov 05 '19 at 22:53