在使用 Expression 创建的列表上调用 Select 方法,并在 Select 方法中使用传递的 Func<>

Call Select Method on List created using Expression and use a passed Func<> within the Select method

我只是想这样做:

(inputObj ) => (inputObj .Select(objEln=> hubObjectConverter(objEln)));

inputObj ----> List<elnObject> 

hubObjectConverter ----> Func<object,object>

我哪里错了?

var typeElnObjList = typeof(List<>).MakeGenericType(new[] { elnObjectType });
var inputObj = Expression.Parameter(typeElnObjList, "lstElnObj");

var paramSelectMeth = Expression.Parameter(elnObjectType, "objEln");
var convertToObject = Expression.Invoke(Expression.Constant(hubObjectConverter), paramSelectMeth);
var lambdaSelect = Expression.Lambda(convertToObject, paramSelectMeth);

var convertList = Expression.Call(typeof(Enumerable), 
                                   "Select", 
                                   new[] { elnObjectType, hubObjectType }, 
                                   inputObj, 
                                   lambdaSelect);  <------ I keep getting an error here. Saying Select cannot accept generic type. Where am I going wrong?

(我假设你的问题是an X/Y problem,所以我不会从表面上回答你的问题)

如果您的意图是允许通过在运行时使用 Type 而不是泛型指定 TOut 的类型来允许从 List<TIn> 转换为 List<TOut> -类型参数那么你只需要 MakeGenericMethod 而你根本不需要使用 Expression<>:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

public static class ListExtensions
{
    public static IList ConvertList<TSource>( this List<TSource> source, Type destinationType, Func<object,object> hubObjectConverter )
    {
        if( source is null ) throw new ArgumentNullException(nameof(source));
        if( destinationType is null ) throw new ArgumentNullException(nameof(destinationType));
        
        //
        
        MethodInfo mi = typeof(ListExtensions)
            .GetMethod( nameof(ConvertListImpl), BindingFlags.Static | BindingFlags.NonPublic )
            .MakeGenericMethod( typeof(TSource), destinationType );

        Object result = mi.Invoke( obj: null, new Object[] { source, hubObjectConverter } );
        return (IList)result;
    }

    private static List<TOut> ConvertListImpl<TIn,TOut>( List<TIn> source, Func<Object,Object> converter )
    {
        return source
            .Select( item => converter( item ) )
            .Cast<TOut>()
            .ToList();
    }
}

(为了提高性能,MethodInfo 可以缓存在 static readonly ConcurrentDictionary<(TIn,TOut),MethodInfo> 字典中)。

它会像这样使用:

List<Int32> listOfInt32 = new List<Int32>() { 1, 2, 3, 4, 5 };

IList listOfString = listOfInt32.ConvertList( destinationType: typeof(String), obj => obj.ToString() );

即使 listOfString 静态类型为 IList,它的实际运行时类型是 List<String>.

如果知道来源类型,那就是匿名类型。所以将其转换为对象类型

 class Address
    {
        public string Street { get; set; }
        public Foo Foo { get; set; }
    }

    class User
    {
        public string Name { get; set; }
        public Address Address { get; set; }
    }


     public static List<object> ConvertToListOfObjects<T>(List<T> list)
        {
            return list.ConvertAll<object>(t => t);
        }

    static void Converttotarget()
        {
            User testUser = new User()
            {
                Name = "Paul",
                Address = new Address()
                {
                    Street = "Freeway",
                    Foo = new Foo() { Bar = "Baz" }
                }
            };
            var users = new List<User>();
            users.Add(testUser);

            var objusers = ConvertToListOfObjects(users);

            var testbj = new { name = "test", rol = 1 };
            var objelist = new List<object>();
            objelist.Add(testbj);

            var lst = ConvertToListOfObjects(objelist);
        }