如何创建一个Extension方法,在运行时将List <t>转换为另一个不同类型的List <t>?</t> </t>

时间:2013-04-11 13:31:09

标签: c# generics type-conversion

我知道之前已经问过这个,但我尝试的解决方案从未考虑过可空类型。

我需要一些能够处理转换的东西,比如

  

列表与LT;串GT; to List&lt; Int32?&gt ;, List&lt; string&gt; to List&lt; int&gt ;, List&lt; string&gt;   列出&lt; double&gt;

我正在尝试创建如下内容

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;
    }

任何人都可以帮我解决这个问题吗?

谢谢!

5 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

您所谈论的转化本身并非转换,而是类型转换。

你可以使用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()将它们列入列表。

答案 2 :(得分:0)

你可以试试这个:

public static IEnumerable<TTo> ChangeType<TTo, TFrom>(this IEnumerable<TFrom> self)
{
    return self.Select(e => (TTo)Convert.ChangeType(e, typeof(TTo)));
}

修改

如果你不想使用泛型,你必须传递类型: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);
   }
}

答案 3 :(得分:0)

这是一个简单的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));
}

答案 4 :(得分:0)

Convert类不能处理Nullable类型,所以我必须特殊情况。

 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);
        }
    }