使用两个参数为lambda声明提供的参数数量不正确

时间:2015-05-09 23:55:05

标签: c# extension-methods

我有查询

return this._articlesRepository.GetEntities()
            .Join(this._categoryRepository.GetEntities(),
                article => article.CategoryId,
                cat => cat.Id, (article, cat) => new {article, CategoryName = cat.Title}).Select(new T());

我有select的可查询扩展名。我尝试为动态生成的选择查询创建扩展。

public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, TResult result)
    {
        var resultType = typeof(TResult);
        var resultObj = Expression.New(resultType);
        var receiverProperties = resultType.GetProperties();
        Type type = typeof(TSource);
        ParameterExpression sourceParameter = Expression.Parameter(type, "item");
        ParameterExpression anyParameter = null;
        var resultParameters = new List<MemberBinding>();

        foreach (var receiverProperty in receiverProperties)
        {
            var sourceProperty = typeof(TSource).GetProperty(receiverProperty.Name);

            if (sourceProperty != null)
            {
                var sourcePropertyAccess = Expression.MakeMemberAccess(sourceParameter, sourceProperty);
                var memberInit = Expression.Bind(receiverProperty, sourcePropertyAccess);
                resultParameters.Add(memberInit);
            }
        }

        if (typeof(TSource).Name.Contains("AnonymousType"))
        {
            foreach (var property in typeof(TSource).GetProperties())
            {
                if (property.PropertyType.BaseType == typeof(BaseEntity))
                {
                    anyParameter = Expression.Parameter(property.PropertyType, "item."+property.Name);

                    foreach (var receiverProperty in receiverProperties)
                    {
                        var sourceProperty = property.PropertyType.GetProperty(receiverProperty.Name);

                        if (sourceProperty != null)
                        {
                            var sourcePropertyAccess = Expression.MakeMemberAccess(anyParameter, sourceProperty);
                            var memberInit = Expression.Bind(receiverProperty, sourcePropertyAccess);
                            resultParameters.Add(memberInit);
                        }
                    }
                }
            }
        }

        if (anyParameter != null)
        {
            var selector = Expression.Lambda<Func<TSource, TResult>>(Expression.MemberInit(resultObj, resultParameters), sourceParameter, anyParameter);
            var method = Expression.Call(typeof(Queryable), "Select", new[] { source.ElementType, selector.Body.Type }, source.Expression, Expression.Quote(selector));
            return source.Provider.CreateQuery<TResult>(method);
        }
        else
        {
            var selector = Expression.Lambda<Func<TSource, TResult>>(Expression.MemberInit(resultObj, resultParameters), sourceParameter);
            var method = Expression.Call(typeof(Queryable), "Select", new[] { source.ElementType, selector.Body.Type }, source.Expression, Expression.Quote(selector));
            return source.Provider.CreateQuery<TResult>(method);
        }
    }

但是我的代码在这一刻落下了

var selector 
   = Expression.Lambda<Func<TSource, TResult>>
       (Expression.MemberInit(resultObj, resultParameters),
        sourceParameter, 
        anyParameter);

我无法理解为什么?我明白我的代码看起来很糟糕。但后来我解决了这个问题。

我的旧代码工作正常

 public static IQueryable<TResult> Select<TSource, TResult>(this IQueryable<TSource> source, TResult result)
    {
        var resultType = typeof(TResult);
        var resultObj = Expression.New(resultType);
        var receiverProperties = resultType.GetProperties();
        Type type = typeof(TSource);
        ParameterExpression sourceParameter = Expression.Parameter(type, "item");
        var resultParameters = new List<MemberBinding>();

        foreach (var receiverProperty in receiverProperties)
        {
            var sourceProperty = typeof(TSource).GetProperty(receiverProperty.Name);

            if (sourceProperty != null)
            {
                var sourcePropertyAccess = Expression.MakeMemberAccess(sourceParameter, sourceProperty);
                var memberInit = Expression.Bind(receiverProperty, sourcePropertyAccess);
                resultParameters.Add(memberInit);
            }
        }
            var selector = Expression.Lambda<Func<TSource, TResult>>(Expression.MemberInit(resultObj, resultParameters), sourceParameter);
            var method = Expression.Call(typeof(Queryable), "Select", new[] { source.ElementType, selector.Body.Type }, source.Expression, Expression.Quote(selector));
            return source.Provider.CreateQuery<TResult>(method);
    }

0 个答案:

没有答案