How to return an IQueryable<Something> as an IQueryable<ISomething>
I have a class Something
that implements ISomething
. How can I convert/cast from an IQueryable<Something>
to an IQueryable<ISomething>
. When I try to cast, I am able to compile, but the result of the cast is always NULL.
Background: The reason I am doing this is because my Something
class is a CodeSmith-generated class (PLINQO template) that has table mapping decoration, methods, etc. My ISomething
interface is "POCO-style", in that it is dumb and simply mirrors the properties of the Something
class. It also exists in it's own namespace. I am doing this so I don't have to reference the assembly that holds the Something开发者_运维百科
class from my service layer. The assembly that holds the Something
class will only need to be referenced in my repository layer now.
To understand what's going on here, it's important to look at this from the perspective of the type system. To the type system, Something
and ISomething
are two types that have an inheritence-like relationship (implementation is not exactly inheritance, but close). The generic types IQueryable<Something>
and IQueryable<ISomething>
do not have this relationship. They are two completely different types, and belong to a completely different part of the inheritance tree (the branch that includes IQueryable) than either Something or ISomething.
So when casting from IQuerable<Something>
to IQueryable<ISomething>
, as far as the type system is concerned you might as well try to cast from IQueryable<double>
to IQueryable<IDataRecord>
. The result is the same: it doesn't know how to make that conversion, and so the as
operator returns null.
One solution to this problem (not the problem itself, as indicated by others) called covariance is implemented in C# 4.0. .Net Type Variance allows the type system to have a limited understanding of the specialization relationship between two different types that specialize the same generic type, so that when casting from one to the other the type can vary (note the root word here).
For code prior to .Net 4, you have to use something like the .Cast<T>()
extension method. But this is less ideal, because it forces a real cast operation, where type variance lets the framework use the actual type that's already there.
You can use LINQ method Cast
IQueryable<Something> something = ...
IQueryable<ISomething> casted = something.Cast<ISomething>();
There is an excellent explanation of the Covariance problem you are encountering in the answer to this question.
Not how -- but rather, why:
Generic Covariance -- this link will help explain:
C# Generic Covariance
精彩评论