C # Linq Проецирование анонимного типа на интерфейс - PullRequest
7 голосов
/ 12 ноября 2011

Возможно ли проецировать с помощью 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мне объект.

Ответы [ 3 ]

5 голосов
/ 12 ноября 2011

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

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

Ссылка: 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 );
 }
3 голосов
/ 12 ноября 2011

Вы не можете сделать это напрямую с анонимными объектами, но вы можете достичь чего-то очень похожего с Clay framework:

public interface IPerson {
    string FirstName { get; set; }
    string LastName { get; set; }
}

public static void CastToCLRInterface() {
    dynamic New = new ClayFactory();

    var person = New.Person();
    person.FirstName = "Louis";
    person.LastName = "Dejardin";

    // Concrete interface implementation gets magically created!
    IPerson lou = person;

    // You get intellisense and compile time check here
    Console.WriteLine("{0} {1}", lou.FirstName, lou.LastName);
}
0 голосов
/ 12 ноября 2011

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

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

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

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

...