如何将无参数构造函数转换为MemberInitExpression

时间:2013-08-17 13:22:04

标签: linq constructor expression expression-trees

我可以从一个字面上返回无参数构造函数的函数创建一个MemberInitExpression或无参数构造函数的任何表达式吗?

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"
    };
} 

当然以上都没有,但是我只是想避免重复输入相同的无参数构造函数,以便每当我想获得不同的视图时获取视图构造函数。

例如,我想像这样称呼它

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);
}

而不是每次我都称之为相同的无参数构造函数,如下所示..

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"
            }
        }
    };
}

所以我实际上正在寻找转换方式

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

进入MemberInitExpression无参数构造函数,所以也许我可以像下面那样使用它,而不进行任何成员赋值。

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);
}

1 个答案:

答案 0 :(得分: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
    }; 
}

此方法已生成MemberInitExpression。如果你这样做

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

您将获得System.Linq.Expressions.MemberInitExpression

如果你想要的只是传递一些参数,那么传递一些参数:

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
    }; 
}