[英]How to use SetValue of an Indexed Property in Reflection?
我有一個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方法來避免此異常?
這是我的建議:
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方法即可。
這是因為您試圖將索引傳遞給未索引的屬性(數據)。
如果您發布ClassA代碼,我可以嘗試提供幫助。 無論如何,您都可以使用LINQ來執行這種轉換。 它更快(編寫和執行)和鍵入安全。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.