如何创建一个Extension方法来转换List< >到另一个列表运行时不同类型的

本文关键字:另一个 列表 运行时 同类型 List 创建 何创建 一个 方法 Extension 转换 | 更新日期: 2023-09-27 18:08:44

我知道以前有人问过这个问题,但是我尝试过的解决方案从未考虑可空类型。

我需要一些东西能够处理像

这样的转换

List到List<Int32?>, List变为List, ListList<双>

等。

我正在尝试创建如下内容

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;
    }
有谁能帮我解决这个问题吗?

谢谢!

如何创建一个Extension方法来转换List< >到另一个列表<T>运行时不同类型的

如果您可以使用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);
   }
}