Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 942
Brian David Berman Avatar asked Nov 30 '22 18:11

Brian David Berman


2 Answers

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.

like image 80
Joel Coehoorn Avatar answered Mar 15 '23 23:03

Joel Coehoorn


You can use LINQ method Cast

 IQueryable<Something> something = ...
 IQueryable<ISomething> casted = something.Cast<ISomething>();
like image 38
Nagg Avatar answered Mar 15 '23 22:03

Nagg