我需要复制一个匿名通用List<>到一个匿名数组。 事实是我不知道设计时的元素类型。所有必须在运行时使用反射解决。 请阅读代码中的注释以进一步解释问题。 我需要一种新方法来实现这一目标。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace MapperTestLogic
{
public class temp
{
//Source is an Object with Properties of Generic Lists, Destination is an Object with Properties of type Array
//The Property Names are allways the same
public void Copy(object Source, object Destination)
{
Type sourceType = Source.GetType();
Type destinationType = Destination.GetType();
foreach (PropertyInfo sourceProp in sourceType.GetProperties())
{
if (sourceProp.GetValue(Source, null) != null)
{
PropertyInfo destProp = destinationType.GetProperty(sourceProp.Name); //Get the same Property in destination
Type sourceItemType;
Type destItemType;
//Destination is Array, Source inherits from IList..
if (destProp != null && destProp.PropertyType.IsArray && InheritsFromIList(sourceProp, out sourceItemType))
{
//..get the Source
var colSource = ((IEnumerable<dynamic>)sourceProp.GetValue(Source, null)).ToList();
var colDestination = destProp.GetValue(Destination, null);
//..get the Destination Element Type (They are not the same Types as in the List but they have the same name)
Type t = colDestination.GetType();
destItemType = t.GetElementType();
var listType = typeof(List<>);
var constructedListType = listType.MakeGenericType(destItemType);
var listInstance = (IList)Activator.CreateInstance(constructedListType); //Create a new IList-Instance of destination Element Type
foreach (var sourceItem in colSource)
{
//Iterate through sourcitems and create instances of destination type
var di = Activator.CreateInstanceFrom(destItemType.Assembly.CodeBase, destItemType.FullName);
var destItem = di.Unwrap();
di = null;
listInstance.Add(destItem);
}
//Create new Array Instance with the the correct Destination Elementtype in the correct Size..
var arrDestination = Activator.CreateInstance(t, new object[] { listInstance.Count });
//From here on the Code is not working properly
foreach(var item in listInstance)
{
arrDestination[0] = item; //Here I will copy the value but get the compiler Error: Cannot apply indexing with [] to an expression of type object
}
//I know why etc. I need now an other approach to solve my problem.
destProp.SetValue(Destination, arrDestination);
}
}
}
}
private bool InheritsFromIList(PropertyInfo sourceProp, out Type ItemType)
{
ItemType = typeof(NullClass);
foreach (Type interfaceType in sourceProp.PropertyType.GetInterfaces())
{
if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof(IList<>))
{
//if so, work each element of the List
ItemType = sourceProp.PropertyType.GetGenericArguments()[0];
break;
}
}
if (ItemType != typeof(NullClass))
{
return true;
}
else
{
return false;
}
}
}
internal class NullClass
{
//Helperclass for Method InheritsFromIList
}
}
答案 0 :(得分:0)
正如Rob所提到的,您可以使用Enumerable.ToArray<TSource>
Method来创建匿名数组。为确保类型兼容性,您可以使用Type.IsAssignableFrom
Method。
public void Copy(object Source, object Destination)
{
Type sourceType = Source.GetType();
Type destinationType = Destination.GetType();
foreach (PropertyInfo sourceProp in sourceType.GetProperties())
{
var targetProperty = destinationType.GetProperty(sourceProp.Name);
if (targetProperty != null &&
targetProperty.PropertyType.IsArray &&
typeof (IList<>)
.MakeGenericType(targetProperty.PropertyType.GetElementType())
.IsAssignableFrom(sourceProp.PropertyType))
{
var closedGenericMethod =
typeof (Enumerable).GetMethod(nameof(Enumerable.ToArray))
.MakeGenericMethod(targetProperty.PropertyType.GetElementType());
var item = sourceProp.GetValue(Source, null);
var resultArray = closedGenericMethod.Invoke(null, new[] {item});
targetProperty.SetValue(Destination, resultArray);
}
}
}