С# Linq Проецирование анонимного типа на интерфейс

Можно ли проецировать с помощью Select на анонимный тип?

Вот пример кода

public interface ITest
{
    string A{get;}
    int B{get;}
}

string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
IQueryable<ITest> query =
    from     n in names.AsQueryable()
    select   new {A = n.ToUpper(), B = 2012};

Приведенный выше код вызывает

Невозможно неявно преобразовать тип «System.Linq.IQueryable» в «System.Linq.IQueryable».

Примечание. Я могу заставить приведенный выше код работать, если бы я определил класс Test, который реализует ITest, а затем проецирует в этот класс, используя:

select   new Test {A = n.ToUpper(), B = 2012};

Почему? Я пытаюсь понять, могу ли я определить только интерфейс, а не определять конкретную реализацию объекта, и заставить Linq создать мне объект.


person Raj Rao    schedule 12.11.2011    source источник
comment
Почему вам нужен результат IQueryable, а не IEnumerable?   -  person Arnaud F.    schedule 12.11.2011
comment
Я пытаюсь понять, могу ли я определить только интерфейс, а не конкретную реализацию ... без динамической генерации кода этого не произойдет. У вас должен быть конкретный объект. У вас будет либо конкретный тип времени компиляции, либо тип, сгенерированный во время выполнения.   -  person IAbstract    schedule 12.11.2011
comment
IQueryable, потому что на самом деле я иду за базой данных. Приведенный выше код был просто примером   -  person Raj Rao    schedule 13.11.2011


Ответы (3)


Да, вы можете выбрать анонимный тип, но вы не можете одновременно выбрать анонимный тип и затем использовать эти объекты, как если бы они реализовали интерфейс. Причина в том, что анонимный тип не реализует интерфейс, даже если они имеют одинаковые свойства как по типу, так и по имени. Невозможно определить, что анонимный тип реализует интерфейс. Если вы хотите использовать объекты через реализацию их интерфейса, вам нужно выбрать конкретный тип, который реализует этот интерфейс.

Анонимные типы — это типы классов, которые происходят непосредственно от объекта и не могут быть приведены ни к какому типу, кроме объекта. Компилятор предоставляет имя для каждого анонимного типа, хотя ваше приложение не может получить к нему доступ. С точки зрения общеязыковой среды выполнения анонимный тип ничем не отличается от любого другого ссылочного типа.

Ссылка: http://msdn.microsoft.com/en-us/library/bb397696.aspx

Я, конечно, могу сочувствовать вашим намерениям здесь. Было бы неплохо, если бы компилятор мог интуитивно понять, что тип соответствует определению интерфейса, когда тип является анонимным, но на самом деле это применимо только тогда, когда интерфейс состоит исключительно из свойств, доступных только для чтения. В ту минуту, когда ваш интерфейс определяет свойства с помощью сеттеров или методов, анонимный тип не может реализовать его. С другой стороны, если вы используете анонимный тип по назначению — как краткосрочный временный тип для конкретного использования — вы можете просто сослаться на его свойства, и вам вообще не нужен интерфейс.

 var query = from     n in names.AsQueryable()
             select   new {A = n.ToUpper(), B = 2012};
 foreach (var item in query)
 {
      Console.WriteLine( item.A );
 }
person tvanfosson    schedule 12.11.2011
comment
вы можете просто ссылаться на его свойства, и вам вообще не нужен интерфейс. - Я не могу этого сделать, так как метод должен возвращать запрошенные объекты. (Это часть DAL, и я иду против базы данных, а не статического массива). Я просто пытался определить, могу ли я быть ленивым и уйти, не создавая класс! Ваш ответ имеет смысл - я не могу! - person Raj Rao; 13.11.2011


Вы не можете, потому что анонимные типы не реализуют интерфейсы.

Для этого нужно создать класс.

Одним из вариантов может быть Duck Typing Project, который по существу создает оболочку класс во время выполнения (и, следовательно, имеет штраф к производительности и потреблению памяти)

(Просто для справки: анонимные типы — это реальные, конкретные классы, сгенерированные компилятором C#. Сама среда выполнения .net не поддерживает их. Компилятор C# не позволяет изменять способ генерации этих классов. Я не пытался увидеть если здесь может помочь Roslyn.)

person Michael Stum    schedule 12.11.2011
comment
Вы также можете создать этот класс во время выполнения. И из того, что я слышал, нынешнее воплощение Рослин совершенно пассивно. - person CodesInChaos; 12.11.2011
comment
@CodeInChaos Совершенно верно, только что добавил ссылку на проект Duck Typing Project, который делает именно это. Я действительно не рекомендую использовать поколения классов времени выполнения для типов, которые контролирует разработчик, но это действительно вариант. - person Michael Stum; 12.11.2011