将List转换为typeof UnderlyingSystemType

时间:2015-06-17 13:57:01

标签: c# list inheritance reflection dynamic-linq

我目前正在处理使用dynamic-linq的代码,使用$('a[title="' + $title '"]').css("color", "red"); 时遇到问题,其中列表实际上包含List<BaseClass>类的列表。

当我执行以下代码时,我得到Person

ParseException

和例外:

enter image description here

请参阅下面的var list = new List<BaseClass>(); list.Add(new Person { FirstName = "Joe", Surname = "Bloggs" }); list.Where("FirstName == @0", "Joe");

BaseClass

public class BaseClass { public int Id { get; set; } } 类:

Person

我可以通过实施以下代码克服错误:

public class Person : BaseClass
{
   public string FirstName { get; set; }
   public string Surname   { get; set; }
}

请参阅以下var list = new List<BaseClass>(); list.Add(new Person { FirstName = "Joe", Surname = "Bloggs" }); var newList = CreateListOfCorrectType<BaseClass>(list); newList.Where("FirstName == @0", "Joe"); 方法:

CreateListOfCorrectType<T>

我的问题是否使用private IList CreateListOfCorrectType<T>( List<T> list) { if (list.Count == 0) { return list; } var typeInfo = list.FirstOrDefault().GetType(); var correctListType = typeof(List<>).MakeGenericType(typeInfo.UnderlyingSystemType); var listOfCorrectType = (Activator.CreateInstance(correctListType)) as IList; list.ForEach(x => listOfCorrectType.Add(x)); return listOfCorrectType; } 是克服问题的最佳方式?如果没有,我有什么选择让CreateListOfCorrectType得到正确的类型。

我希望将其与现有代码一起使用,并且无法更改现有的List<BaseClass>类型。并且List<>方法不了解CreateListOfCorrectType类。

请注意,类名和变量仅用于演示目的。

更新

以下乐观主义者的回答让我找到了解决问题的方法,请参阅下面使用的扩展方法:

Person

public static IList ToDerivedListType(this IList list) { if (list == null || list.Count == 0) { return list; } var type = list.Cast<object>().FirstOrDefault().GetType(); var castedList = typeof(Enumerable).GetMethod("Cast", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public) .MakeGenericMethod(type) .Invoke(null, new[] { list }); return typeof(Enumerable).GetMethod("ToList", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public) .MakeGenericMethod(type) .Invoke(null, new[] { castedList }) as IList; } System.Linq.Enumerable.Cast是关键。

2 个答案:

答案 0 :(得分:2)

如何使用OfType linq方法:

list.OfType<Person>().Where("FirstName == @0", "Joe");

请参阅https://msdn.microsoft.com/en-us/library/vstudio/bb360913(v=vs.100).aspx

答案 1 :(得分:0)

根据实际使用情况,可以改进一些事项:

  • 运行时开销:CreateListOfCorrectType函数将所有元素复制到一个新集合中,如果只从返回的集合中取出一个子集,则会导致不必要的费用。
  • 映射函数的适用范围:可以将其扩展为与IEnumerable一起使用。
  • 最后,映射和过滤功能可以合并为一个,以减少消费功能中的代码量。
可以使用

System.Linq.Enumerable.CastMakeGenericMethod来实现这一目标:

static public class Extension
{
    static public IEnumerable CastDynamic(this  IEnumerable Source, Type Type)
    {
        return
            (IEnumerable)
            typeof(Enumerable)
            .GetMethod("Cast", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)
            .MakeGenericMethod(Type)
            .Invoke(null, new[] { Source });
    }

    static public IEnumerable CastToFirstType(this  IEnumerable Source)
    {
        if (0 == Source.Take(1).Count())
        {
            return Source;
        }

        return CastDynamic(Source, Source.Cast<object>().FirstOrDefault().GetType());
    }

    static public IEnumerable WhereCastToFirstType(this IEnumerable Source, string Predicate, params object[] values)
    {
        return Source.CastToFirstType().Where(Predicate, values);
    }
}

如果尝试模仿您在抛出的异常方面显示的功能。有一点不同,因为在映射函数返回后完成了转换。