如何创建一个Extension方法来转换List< >到另一个列表运行时不同类型的
本文关键字:另一个 列表 运行时 同类型 List 创建 何创建 一个 方法 Extension 转换 | 更新日期: 2023-09-27 18:08:44
我知道以前有人问过这个问题,但是我尝试过的解决方案从未考虑可空类型。
我需要一些东西能够处理像
这样的转换List
到List<Int32?>, List 变为List , List List<双>双>
等。
我正在尝试创建如下内容
private void RoutineCompleted(string category, List Type fieldType = null)
{
//ToNewType is the extension method that I need.
var var convertedList = values.ToNewType(fieldType);
}
我看了下面的代码,但它没有完成工作:
public static IEnumerable Cast(this IEnumerable self, Type innerType)
{
var methodInfo = typeof(Enumerable).GetMethod("Cast");
var genericMethod = methodInfo.MakeGenericMethod(innerType);
return genericMethod.Invoke(null, new object[] { self }) as IEnumerable;
}
有谁能帮我解决这个问题吗?谢谢!
如果您可以使用Convert.To...
方法进行转换,则不需要扩展
List<string> strList = ...
List<int> intList = strList.Select(s => Convert.ToInt32(s)).ToList();
也可以用Convert.ChangeType
public static IEnumerable<TOut> ConvertTo<TIn, TOut>(this IEnumerable<TIn> list)
{
return list.Select(o => (TOut)Convert.ChangeType(o, typeof (TOut)));
}
List<string> strList = new List<string>();
IEnumerable<int> intList = strList.ConvertTo<string, int>();
你所说的转换本身不是类型转换,而是类型转换。
你可以用Linq来做,例如:
var ints = new List(){1,2,3,4,51};
var strings = array.Select(x => x.ToString());
或
var strings = new List() {"1.56","2.71","3.14"};
var doubles = strings.Select( x => Convert.ToDouble(x));
这些给你IEnumerables,但你可以使他们成为列表使用.ToList()
。
Convert类不能处理可空类型,所以我必须对它们进行特殊处理。
static void Main(string[] args)
{
var strings = new[] { "1","2","3"};
var ints = strings.ConvertItems<string, int>().ToList();
var doubles = strings.ConvertItems<string, double>().ToList();
var nullableints = strings.ConvertItems<string, int?>().ToList();
}
public static IEnumerable<TargetType> ConvertItems<SourceType, TargetType>(this IEnumerable<SourceType> sourceCollection)
{
var targetType = typeof(TargetType);
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
targetType = targetType.GetGenericArguments().First();
}
return sourceCollection.ConvertItems((source) => (TargetType)Convert.ChangeType(source, targetType));
}
public static IEnumerable<TargetType> ConvertItems<SourceType, TargetType>(this IEnumerable<SourceType> sourceCollection, Converter<SourceType, TargetType> convertor)
{
foreach (var item in sourceCollection)
{
yield return convertor(item);
}
}
编辑:弱类型版本,当你只在运行时知道类型
static void Main(string[] args)
{
var strings = new[] { "1","2","3"};
var ints = strings.ConvertItems(typeof(int));
var doubles = strings.ConvertItems(typeof(double));
var nullableints = strings.ConvertItems(typeof(int?));
foreach (int? item in nullableints)
{
Console.WriteLine(item);
}
}
public static IEnumerable ConvertItems(this IEnumerable sourceCollection,Type targetType)
{
if (targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>))
{
targetType = targetType.GetGenericArguments().First();
}
foreach (var item in sourceCollection)
{
yield return Convert.ChangeType(item, targetType);
}
}
这是一个简单的LINQ Select
:
IEnumerable<string> values = new[] { "1", "2", "3" };
var converted = values.Select(PerformConversion);
private int? PerformConversion(string input)
{
...
}
您将需要为每个转换使用不同的方法,或者使用参数化方法来包含所有转换。例如:
private T? PerformConversion<T>(string input) where T : struct, IConvertible
{
return (T?) Convert.ChangeType(input, typeof(T));
}
你可以试试:
public static IEnumerable<TTo> ChangeType<TTo, TFrom>(this IEnumerable<TFrom> self)
{
return self.Select(e => (TTo)Convert.ChangeType(e, typeof(TTo)));
}
编辑:如果你不想使用泛型,你必须像这样传递type: Type
:
var list = new List<string> {"1", "3", "4", null};
var result = list.ChangeType(typeof (int?));
你可以试着这样写:
public static IEnumerable ChangeType(this IEnumerable self, Type type)
{
var converter = TypeDescriptor.GetConverter(type);
foreach (var obj in self)
{
yield return converter.ConvertFrom(obj);
}
}