将 List 转换为 typeof UnderlyingSystemType
Convert List to typeof UnderlyingSystemType
我目前正在处理使用 dynamic-linq 的代码,我 运行 在使用 List<BaseClass>
时遇到问题,其中列表实际上包含 [=17] 的列表=] Class.
当我执行下面的代码时,我得到一个 ParseException
:
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
class:
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
class.
请注意 class 名称和变量仅用于说明目的。
更新
下面乐观主义者的回答让我找到了问题的解决方案,请参阅下面使用的扩展方法:
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
是关键。
如何使用 OfType linq 方法:
list.OfType<Person>().Where("FirstName == @0", "Joe");
见https://msdn.microsoft.com/en-us/library/vstudio/bb360913(v=vs.100).aspx
根据实际用例,有些地方可以改进:
- 运行时开销:
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);
}
}
如果试图模仿您在抛出异常方面展示的功能。存在差异,因为转换是在映射函数 returns.
之后完成的
我目前正在处理使用 dynamic-linq 的代码,我 运行 在使用 List<BaseClass>
时遇到问题,其中列表实际上包含 [=17] 的列表=] Class.
当我执行下面的代码时,我得到一个 ParseException
:
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
class:
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
class.
请注意 class 名称和变量仅用于说明目的。
更新
下面乐观主义者的回答让我找到了问题的解决方案,请参阅下面使用的扩展方法:
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
是关键。
如何使用 OfType linq 方法:
list.OfType<Person>().Where("FirstName == @0", "Joe");
见https://msdn.microsoft.com/en-us/library/vstudio/bb360913(v=vs.100).aspx
根据实际用例,有些地方可以改进:
- 运行时开销:
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);
}
}
如果试图模仿您在抛出异常方面展示的功能。存在差异,因为转换是在映射函数 returns.
之后完成的