Linq where-filter 导致强制转换为基础 class
Linq where-filter causes cast to base class
我有一个具体的通用 IQueryable class:
IQueryable<Person> result = GetAllEmployees(); //returns IQueryable<Employee>
如果我 return result
在 service-call 中 Breeze-Entitytype,一切正常:
breeze.EntityQuery.from("Employees").orderBy("EmployeeID");
一旦我在 service-call 中的 result
中添加一个 where-filter,整个 IQueryable-Object 似乎被铸造到基础 class Person
不再有 属性 EmployeeID
:
IQueryable<Person> result = GetAllEmployees(); //returns IQueryable<Employee>
result = result.Where(o => myHashSet.Contains(o.Id));
这会导致以下错误:
Microsoft.Data.OData.ODataException: The query specified in the URI is not valid. Could not find a property named 'EmployeeID' on type 'Person'.
显然,where
将 IQueryable
包装到一个新的 IQueryable
中,其存储的变量类型。原始 IQueryable 的 ElementType
丢失了.
当您在 where
处中断并检查 result.ElementType
时,您可以看到这一点。一旦您跨过 where
,它就会从 Employee
变为 Person
。
通过以下代码,我们恢复了 ElementType(在 where
之前用 result.ElementType
喂养它):
public static IQueryable<T> ToTypedQueryable<T>(this IEnumerable<T> source, Type theType, bool exact = false) {
if (source == null) throw new ArgumentNullException("source");
System.Collections.IList result = (System.Collections.IList)typeof(List<>)
.MakeGenericType(theType)
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
foreach (var s in source) {
Type t = s.GetType();
if (t == theType) {
result.Add(s);
} else if (!exact && t.IsSubclassOf(theType)) {
result.Add(s);
}
}
return (IQueryable<T>)(result.AsQueryable());
}
我有一个具体的通用 IQueryable class:
IQueryable<Person> result = GetAllEmployees(); //returns IQueryable<Employee>
如果我 return result
在 service-call 中 Breeze-Entitytype,一切正常:
breeze.EntityQuery.from("Employees").orderBy("EmployeeID");
一旦我在 service-call 中的 result
中添加一个 where-filter,整个 IQueryable-Object 似乎被铸造到基础 class Person
不再有 属性 EmployeeID
:
IQueryable<Person> result = GetAllEmployees(); //returns IQueryable<Employee>
result = result.Where(o => myHashSet.Contains(o.Id));
这会导致以下错误:
Microsoft.Data.OData.ODataException: The query specified in the URI is not valid. Could not find a property named 'EmployeeID' on type 'Person'.
显然,where
将 IQueryable
包装到一个新的 IQueryable
中,其存储的变量类型。原始 IQueryable 的 ElementType
丢失了.
当您在 where
处中断并检查 result.ElementType
时,您可以看到这一点。一旦您跨过 where
,它就会从 Employee
变为 Person
。
通过以下代码,我们恢复了 ElementType(在 where
之前用 result.ElementType
喂养它):
public static IQueryable<T> ToTypedQueryable<T>(this IEnumerable<T> source, Type theType, bool exact = false) {
if (source == null) throw new ArgumentNullException("source");
System.Collections.IList result = (System.Collections.IList)typeof(List<>)
.MakeGenericType(theType)
.GetConstructor(Type.EmptyTypes)
.Invoke(null);
foreach (var s in source) {
Type t = s.GetType();
if (t == theType) {
result.Add(s);
} else if (!exact && t.IsSubclassOf(theType)) {
result.Add(s);
}
}
return (IQueryable<T>)(result.AsQueryable());
}