私はある種の逆シリアル化を実装していて、次の問題に苦労しています:
私はList<object>
とSystem.Reflection.Field
を持っています。FieldType
はList<string>
、List<int>
、またはList<bool>
のいずれかなので、List<object>
からその型に変換する必要があります。
public static object ConvertList(List<object> value, Type type)
{
//type may be List<int>, List<bool>, List<string>
}
私はそれぞれのケースを別々に書くことができますが、リフレクションを使用するより良い方法があるはずです。
私はあなたが望むものは次のとおりだと信じています:
public static object ConvertList(List<object> value, Type type)
{
var containedType = type.GenericTypeArguments.First();
return value.Select(item => Convert.ChangeType(item, containedType)).ToList();
}
使用例:
var objects = new List<Object> { 1, 2, 3, 4 };
ConvertList(objects, typeof(List<int>)).Dump();
ただし、これがどれほど便利かはわかりません...非常に便利なConvert.ChangeTypeメソッドを強調しています。
Update:他の人はこれが実際にはList<T>
(Tは問題の型)を返さないことを正しく指摘しているため、目の前の質問に完全に答えることはできないかもしれませんが、私はより最新の答えを提供することを選択しました:
public static object ConvertList(List<object> items, Type type, bool performConversion = false)
{
var containedType = type.GenericTypeArguments.First();
var enumerableType = typeof(System.Linq.Enumerable);
var castMethod = enumerableType.GetMethod(nameof(System.Linq.Enumerable.Cast)).MakeGenericMethod(containedType);
var toListMethod = enumerableType.GetMethod(nameof(System.Linq.Enumerable.ToList)).MakeGenericMethod(containedType);
IEnumerable<object> itemsToCast;
if(performConversion)
{
itemsToCast = items.Select(item => Convert.ChangeType(item, containedType));
}
else
{
itemsToCast = items;
}
var castedItems = castMethod.Invoke(null, new[] { itemsToCast });
return toListMethod.Invoke(null, new[] { castedItems });
}
変換が不要な場合(各値のタイプが実際に正しく、文字列に整数がない場合など)、performConversion
フラグと関連するブロックを削除します。
タイプは実行時にのみ知られるので、私はジェネリックメソッドは行く方法ではないと思います
public static object ConvertList(List<object> value, Type type)
{
IList list = (IList)Activator.CreateInstance(type);
foreach (var item in value)
{
list.Add(item);
}
return list;
}
これがまったく役立つかどうかはわかりませんが、Linq Castを使用できますか?
List<object> theList = new List<object>(){ 1, 2, 3};
List<int> listAsInt = theList.Cast<int>();
public static object ConvertList<T>(List<object> value) where T : class
{
var newlist = value.Cast<T>().ToList();
return newlist;
}
または
public static List<T> ConvertList<T>(List<object> value) where T : class
{
List<T> newlist = value.Cast<T>().ToList();
return newlist;
}
これを試して:
public static List<T> ConvertList<T>(List<object> list)
{
List<T> castedList = list.Select(x => (T)x);
return castedList;
}
コール:
List<object> myList = new List<object> {"test", "foo", "bar"};
List<string> stringList = ConvertList<string>(myList);
/// <summary>
/// Converts list of items into typed list of item of new type
/// </summary>
/// <example><code>
/// Consider source to be List<object>, newItemType is typeof(string), so resulting list wil have type List<string>
/// </code></example>
/// <param name="newItemType">New item type</param>
/// <param name="source">List of objects</param>
/// <returns>Typed List object</returns>
public static IList ConvertList(Type newItemType, IList source)
{
var listType = typeof(List<>);
Type[] typeArgs = { newItemType };
var genericListType = listType.MakeGenericType(typeArgs);
var typedList = (IList)Activator.CreateInstance(genericListType);
foreach (var item in source)
{
typedList.Add(item);
}
return typedList;
}
public static List<T> ConvertType<T>(List<object> list) {
var list2 = new List<T>();
for(int i=0;i<list.Count;i++) list2.Add((T)list[i]);
return list2;
}