微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何编写用于在 SelectMany 内部进行选择的表达式树?

如何解决如何编写用于在 SelectMany 内部进行选择的表达式树?

考虑以下 Person

    // Person.cs
    public class Person
    {
        public Guid Id { get; set; }
        public string Name { get; set; }
        public string FamilyName { get; set; }
        public float Age { get; set; }
        public DateTimeOffset BithDate { get; set; }
        public IEnumerable<Address> Addresses { get; set; }
        public Person()
        {
            Addresses = new List<Address>();
        }
    }

    // Address.cs
    public class Address
    {
        public string Country { get; set; }
        public string City { get; set; }
        public string MainStreet { get; set; }
        public string Info { get; set; }
        public string No { get; set; }
    }

现在,我有下面的代码片段

var list = PeopleDataGenerator.GetPeople()
    .SelectMany(x => x.Addresses)
    .Select(x => x.City)
    ;

如何使用表达式树完成这部分.SelectMany(x => x.Addresses) .Select(x => x.City)

解决方法

不清楚您是要IEnumerable还是IQueryable...对于IEnumerable

给定:

/// <summary>
/// IEnumerable&lt;TResult&gt; Enumerable.SelectMany&lt;TSource,TResult&gt;(IEnumerable&lt;TSource&gt; source,Func&lt;TSource,IEnumerable&lt;TResult&gt;&gt; selector)
/// </summary>
public static readonly MethodInfo SelectMany1 = (from x in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                                                    where x.Name == nameof(Enumerable.SelectMany)
                                                    let args = x.GetGenericArguments()
                                                    where args.Length == 2
                                                    let pars = x.GetParameters()
                                                    where pars.Length == 2 &&
                                                        pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(args[0]) &&
                                                        pars[1].ParameterType == typeof(Func<,>).MakeGenericType(args[0],typeof(IEnumerable<>).MakeGenericType(args[1]))
                                                    select x).Single();

/// <summary>
/// IEnumerable&lt;TResult&gt; Enumerable.Select&lt;TSource,TResult&gt; selector)
/// </summary>
public static readonly MethodInfo Select1 = (from x in typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)
                                                where x.Name == nameof(Enumerable.Select)
                                                let args = x.GetGenericArguments()
                                                where args.Length == 2
                                                let pars = x.GetParameters()
                                                where pars.Length == 2 &&
                                                    pars[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(args[0]) &&
                                                    pars[1].ParameterType == typeof(Func<,args[1])
                                                select x).Single();

(我有一个完整的 gist 定义)

你可以

// SelectMany
var par1 = Expression.Parameter(typeof(Person));
var sub1 = Expression.Property(par1,nameof(Person.Addresses));
var lambda1 = Expression.Lambda<Func<Person,IEnumerable<Address>>>(sub1,par1);
var selectMany = Expression.Call(SelectMany1.MakeGenericMethod(typeof(Person),typeof(Address)),par0,lambda1);

// Select
var par2 = Expression.Parameter(typeof(Address));
var sub2 = Expression.Property(par2,nameof(Address.City));
var lambda2 = Expression.Lambda<Func<Address,string>>(sub2,par2);
var select = Expression.Call(Select1.MakeGenericMethod(typeof(Address),typeof(string)),selectMany,lambda2);

// persons => Select(SelectMany(persons))
var par0 = Expression.Parameter(typeof(IEnumerable<>).MakeGenericType(typeof(Person)));
var lambda0 = Expression.Lambda<Func<IEnumerable<Person>,IEnumerable<string>>>(select,par0);
var compiled = lambda0.Compile();

如果您想要 SelectMany+Select 调用,它位于 select 变量中。如果您想要使用 SelectMany+Select 的可编译表达式,则它位于 lambda0compiled 中。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。