CreateListOfCorrectType

CreateListOfCorrectType

我目前正在处理使用 dynamic-linq 的代码,在使用 List<BaseClass> 时遇到问题,其中列表实际上包含 Person 类的列表。

当我执行以下代码时,我得到一个 ParseException :

var list = new List<BaseClass>();

list.Add(new Person
{
  FirstName = "Joe",
  Surname   = "Bloggs"
});

list.Where("FirstName == @0", "Joe");

和异常(exception):

请参阅下面的 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.CastMakeGenericMethod 是关键。

最佳答案

根据实际用例,一些事情可以改进:

  • 运行时费用: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);
        }
    }
    

    如果试图模仿您在抛出的异常方面显示的功能。有一个区别,因为转换是在映射函数返回之后完成的。

    关于c# - 将 List 转换为 typeof UnderlyingSystemType,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30893774/

    10-11 21:10