我有一个C#转换器方法,它使用反射来转换通用列表。
当我尝试调用Item属性的SetValue方法时会出现问题,它会抛出以下内部异常(ArgumentOutOfRangeException):
指数超出范围。一定是 非负面且小于集合的大小。参数名称: 索引。
这是我的代码:
internal class Program
{
private static void Main()
{
List<ClassA> classA = new List<ClassA>();
classA.Add(new ClassA { Data = "value1" });
classA.Add(new ClassA { Data = "value2" });
List<ClassB> classB = Converter<List<ClassA>, List<ClassB>>(classA);
}
public static TOut Converter<TIn, TOut>(TIn request)
{
var response = Activator.CreateInstance<TOut>();
PropertyInfo propertyA = typeof(TIn).GetProperty("Item");
PropertyInfo propertyB = typeof(TOut).GetProperty("Item");
int count = (int)typeof(TIn).GetProperty("Count").GetValue(request);
for (int i = 0; i < count; i++)
{
var value = propertyA.GetValue(request, new object[] { i });
var b = CreateBFromA(propertyB, propertyA, value);
propertyB.SetValue(response, b, new object[] { i });
}
return response;
}
private static object CreateBFromA(PropertyInfo propertyB, PropertyInfo propertyA, object value)
{
var b = Activator.CreateInstance(propertyB.PropertyType);
object o = propertyA.PropertyType.GetProperty("Data").GetValue(value);
propertyB.PropertyType.GetProperty("Data").SetValue(b, o);
return b;
}
}
internal class ClassA
{
public string Data { get; set; }
}
internal class ClassB
{
public string Data { get; set; }
public object Other { get; set; }
}
这是一个较大的通用方法的小示例代码(我需要使用反射),因此您可以尝试运行它来重新生成异常。
如何使用SetValue方法来避免此异常?
答案 0 :(得分:1)
以下是我的方法:
public static TCollectionOut ConvertCollection<TCollectionIn, TCollectionOut, TIn, TOut>(TCollectionIn input)
where TCollectionIn : IEnumerable<TIn>
where TCollectionOut : ICollection<TOut>, new()
where TOut : new()
{
var res = new TCollectionOut();
foreach (dynamic item in input)
{
dynamic o = new TOut();
ConvertItem(item, o);
res.Add(o);
}
return res;
}
public static TCollectionOut ConvertCollectionMoreDynamic<TCollectionIn, TCollectionOut>(TCollectionIn input)
where TCollectionIn : IEnumerable
{
dynamic res = Activator.CreateInstance(typeof (TCollectionOut));
var oType = typeof (TCollectionOut).GetMethod("Add").GetParameters().Last().ParameterType;
foreach (dynamic item in input)
{
dynamic o = Activator.CreateInstance(oType);
ConvertItem(item, o);
res.Add(o);
}
return res;
}
public static void ConvertItem(ClassA input, ClassB output)
{
output.Data = input.Data;
}
如果您支持更多类型,只需使用正确的重载创建ConvertItem方法。
答案 1 :(得分:0)
这是因为您尝试将索引传递给非索引属性(Data)。
如果你发布了ClassA代码,我可以试试你的帮助。无论如何,你可以使用LINQ来执行这种转换。它更快(写入和执行)和类型安全。