如何使用反射将运行时类型 A: IList<AT> 的集合转换为类型 B: IList<BT> 的新集合?
How to transform collection with runtime type A: IList<AT> into a new collection of type B: IList<BT> using reflection?
在编译时对类型一无所知。
object TransformObject(object oldObject, Type newType, Func<object, object> transform)
{
if(obj.GetType().ImplementsGenericInterface(typeof(IList<>))
&& newType.ImplementsGenericInterface(typeof(IList<>)))
{
object newCollection = Activator.CreateInstance(newType);
// This is where it gets tricky:
// 1. How to iterate over the old collection?
// 2. How to add each element in the new collection?
object oldCollection = oldObject as IEnumerable;
foreach(var oldItem in oldCollection)
{
object newItem = transform(oldItem);
newCollection.Add(newItem);
}
// 3. How to ensure that the order in the new collection is preserved?
return newCollection;
}
return null;
}
这自然不行
运行 时已知的信息:
oldCollection.GetType()
实现类型 IList<AT>
。
newType
实现类型 IList<BT>
- 函数
object transform(object oldObject)
负责将类型 AT
的对象转换为类型 BT
的新对象。或者将对象映射到不同类型的对象。映射在编译时未知。
试试这个解决方案:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Test
{
static bool ImplementsGenericInterface(Type type, Type genericInterface)
{
return type.GetInterfaces().Any(i => i.GetGenericTypeDefinition() == genericInterface);
}
static object TransformObject(object oldObject, Type newType, Func<object, object> transform)
{
if (ImplementsGenericInterface(oldObject.GetType(), typeof(IList<>))
&& ImplementsGenericInterface(newType, typeof(IList<>)))
{
object newCollection = Activator.CreateInstance(newType);
var method = newType.GetMethod("Add");
foreach (var item in (IEnumerable)oldObject)
{
var newItem = transform(item);
method.Invoke(newCollection, new object[] { newItem });
}
return newCollection;
}
return null;
}
public static void Main()
{
var list1 = new List<int>() { 1, 2, 3 };
var list2 = (List<string>)TransformObject(list1, typeof(List<string>), o => o.ToString());
foreach (var item in list2)
Console.WriteLine(item);
Console.ReadKey();
}
}
在编译时对类型一无所知。
object TransformObject(object oldObject, Type newType, Func<object, object> transform)
{
if(obj.GetType().ImplementsGenericInterface(typeof(IList<>))
&& newType.ImplementsGenericInterface(typeof(IList<>)))
{
object newCollection = Activator.CreateInstance(newType);
// This is where it gets tricky:
// 1. How to iterate over the old collection?
// 2. How to add each element in the new collection?
object oldCollection = oldObject as IEnumerable;
foreach(var oldItem in oldCollection)
{
object newItem = transform(oldItem);
newCollection.Add(newItem);
}
// 3. How to ensure that the order in the new collection is preserved?
return newCollection;
}
return null;
}
这自然不行
运行 时已知的信息:
oldCollection.GetType()
实现类型IList<AT>
。newType
实现类型IList<BT>
- 函数
object transform(object oldObject)
负责将类型AT
的对象转换为类型BT
的新对象。或者将对象映射到不同类型的对象。映射在编译时未知。
试试这个解决方案:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
public class Test
{
static bool ImplementsGenericInterface(Type type, Type genericInterface)
{
return type.GetInterfaces().Any(i => i.GetGenericTypeDefinition() == genericInterface);
}
static object TransformObject(object oldObject, Type newType, Func<object, object> transform)
{
if (ImplementsGenericInterface(oldObject.GetType(), typeof(IList<>))
&& ImplementsGenericInterface(newType, typeof(IList<>)))
{
object newCollection = Activator.CreateInstance(newType);
var method = newType.GetMethod("Add");
foreach (var item in (IEnumerable)oldObject)
{
var newItem = transform(item);
method.Invoke(newCollection, new object[] { newItem });
}
return newCollection;
}
return null;
}
public static void Main()
{
var list1 = new List<int>() { 1, 2, 3 };
var list2 = (List<string>)TransformObject(list1, typeof(List<string>), o => o.ToString());
foreach (var item in list2)
Console.WriteLine(item);
Console.ReadKey();
}
}