在使用 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);
}
我只是想这样做:
(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);
}