/// <summary> /// This will never return null /// </summary> public Func <IQueryable <TSource>, IEnumerable <TDest> > GetProjection() { return(source => source .Select(_sourceTypeToInterimTypeConversion.GetTypeConverterFuncExpression()) .AsEnumerable() .Select(_interimTypeToDestTypeConversion.Convert)); }
private Expression GetEnumerableConversionExpression(Expression propertyValueParam) { if (propertyValueParam == null) { throw new ArgumentNullException("propertyValueParam"); } if (!typeof(IEnumerable <TPropertyOnSourceElement>).IsAssignableFrom(propertyValueParam.Type)) { throw new ArgumentException("propertyValueParam.Type must match be assignable to IEnumerable<TPropertyOnSourceElement>"); } // This translation (using LINQ's Select method) from IEnumerable<TPropertyOnSourceElement> to IEnumerable<TPropertyAsRetrievedElement> is supported // by Entity Framework and may be used for the translation of IQueryable results var selectMethod = typeof(Enumerable).GetMethods() .Select(m => new { Method = m, GenericArguments = m.GetGenericArguments(), Parameters = m.GetParameters() }) .Where(m => (m.Method.Name == "Select") && (m.GenericArguments.Length == 2) && (m.Parameters.Length == 2) && (m.Parameters[0].ParameterType == typeof(IEnumerable <>).MakeGenericType(m.GenericArguments[0])) && (m.Parameters[1].ParameterType == typeof(Func <,>).MakeGenericType(m.GenericArguments[0], m.GenericArguments[1])) ) .Select(m => m.Method.MakeGenericMethod(typeof(TPropertyOnSourceElement), typeof(TPropertyAsRetrievedElement))) .Single(); return(Expression.Call( selectMethod, propertyValueParam, _typeConverter.GetTypeConverterFuncExpression() )); }