我目前正在处理使用 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.Cast
和 MakeGenericMethod
是关键。 最佳答案
根据实际用例,一些事情可以改进:
CreateListOfCorrectType
函数将所有元素复制到新集合中,这会导致不必要的费用,以防仅从返回的集合中取出一个子集。 IEnumerable
一起使用。 System.Linq.Enumerable.Cast
和 MakeGenericMethod
可以用来实现: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/