Преобразовать объект в IEnumerable анонимного типа

Как перебрать anonymous type, который передается как объект ниже (first, second, third) => new { One = first, Two = second, Three = third }

Если я запрошу тип сообщения и распечатаю его, он скажет: <>f__AnonymousType0 3[MtApi.MtQuote,MtApi.MtQuote,MtApi.MtQuote]

//**How do I convert an object to the anonymous type?**
static void ShowAnonymousTypeMessage(object message)
{    

    foreach(var quote in message)
    Console.WriteLine(
        quote.Instrument + ": " + quote.Bid.ToString() + quote.Ask.ToString());
}

...

var pattern = observable1.And(observable2).And(observable3);
var plan = pattern.Then((first, second, third) => new { One = first, Two = second, Three = third });
var zippedSequence = Observable.When(plan);
zippedSequence.Subscribe(
    ShowAnonymousTypeMessage                
);

person Ivan    schedule 05.05.2017    source источник
comment
Можете ли вы установить точку останова и опросить шаблон, чтобы узнать, какой это тип и реализует ли он IEnumerable?   -  person Kevin Raffay    schedule 05.05.2017
comment
В C#‹=6 вы могли бы сделать это с помощью dynamic, но на самом деле это не то, для чего нужны анонимные типы, а dynamic не предназначено для превращения C# в JavaScript. Если вы передаете его методу, он должен иметь реальный тип. Даже Кортеж был бы чем-то.   -  person 15ee8f99-57ff-4f92-890c-b56153    schedule 05.05.2017
comment
@ kevin см. исходный пост   -  person Ivan    schedule 05.05.2017
comment
Это руководство по программированию говорит, что вы не можете объявить формальный параметр метода, свойства, конструктора или индексатора как имеющий анонимный тип. Чтобы передать анонимный тип ... в качестве аргумента метода, вы можете объявить параметр как объект типа. Однако это противоречит цели строгой типизации. Если вам необходимо сохранить результаты запроса или передать их за пределы метода, рассмотрите возможность использования обычной именованной структуры или класса вместо анонимного типа.   -  person Quantic    schedule 05.05.2017
comment
@ed да, кортеж будет работать, так как с ним легко справиться.   -  person Ivan    schedule 05.05.2017
comment
@Ivan Это почти наверняка ситуация, когда вам нужно просто создать объект.   -  person Servy    schedule 05.05.2017
comment
Однако я только что попробовал подпись dynamic theAnonymousType вместо object theAnonymousType, и все работает нормально.   -  person Quantic    schedule 05.05.2017
comment
@Quantic, правда? Я изменил его с объекта на динамический, и он за исключением.   -  person Ivan    schedule 05.05.2017
comment
Э-э, я просто опубликую как ответ, может быть, мой супер простой тест полностью отличается от того, что вы делаете.   -  person Quantic    schedule 05.05.2017
comment
Почему бы не использовать реальный объект? Анонимные объекты действительно не очень хороши, когда они передаются между методами...   -  person Chris    schedule 05.05.2017


Ответы (3)


Это работает для меня:

static void Main()
{
    var anon = new { Name = "Terry", Age = 34 };
    test(anon);
}

static void test(dynamic t)
{
    Console.WriteLine(t.Age);
    Console.WriteLine(t.Name);
}
person Quantic    schedule 05.05.2017
comment
А если их несколько, а не один? - person Ivan; 05.05.2017
comment
@Ivan void Test(dynamic d) { foreach (dynamic item in d) { /* stuff */ } -- проверено, работает. - person 15ee8f99-57ff-4f92-890c-b56153; 05.05.2017
comment
Ага! Спасибо, это то, чего мне не хватает. - person Ivan; 05.05.2017
comment
@Ivan Но, ради бога, напишите быстрый урок или, по крайней мере, используйте Tuple. - person 15ee8f99-57ff-4f92-890c-b56153; 05.05.2017
comment
Согласованный. Динамика здесь кажется излишней. - person Ivan; 05.05.2017
comment
@ Иван, я бы назвал это недостаточным убийством. - person 15ee8f99-57ff-4f92-890c-b56153; 05.05.2017
comment
Или, может быть, Road Kill - person Ivan; 05.05.2017

Анонимные типы не предназначены для передачи, и вы должны использовать объект только в случае крайней необходимости. Также вы не можете перебирать анонимный тип — вы должны использовать Array.

var pattern = observable1.And(observable2).And(observable3);
var plan = pattern.Then((first, second, third) => new[] { first, second, third });
var zippedSequence = Observable.When(plan);
zippedSequence.Subscribe(
    ShowAnonymousTypeMessage                
);
person NetMage    schedule 05.05.2017

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

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

public class Thing {
    public String One { get; set; }
    public String Two { get; set; }
    public String Three { get; set; }
}

Но Tuple<T1,T2,T3> на самом деле так же хорош, если у вас все равно есть имена свойств, такие как One, Two и Three:

public static void Main()
{
    var x = Enumerable.Range(0, 10).Select(n => new Tuple<int, string>(n, $"Item {n + 1}"));

    Test(x);
}

private static void Test(IEnumerable<Tuple<int, string>> stuff)
{
    foreach (var item in stuff)
    {
        Console.Write($"{item.Item1}: {item.Item2}");
    }
}

dynamic работает, но dynamic похож на тиски: «Всегда неправильный инструмент для каждой работы, начиная с 1921 года». dynamic играет законную, но небольшую роль в системе типов. Его там нет, поэтому мы можем превратить весь язык в JavaScript.

public static Main()
{
    var x = Enumerable.Range(0, 10).Select(n => new { ID = n, Value = $"Item {n + 1}" });

    Test(x);
}

private static void Test(dynamic message)
{
    foreach (dynamic item in message)
    {
        Console.Write($"{item.ID}: {item.Value}");
    }
}

Хорошо, Vise-Grip не всегда неправильный инструмент. Но редко бывает лучше.

person 15ee8f99-57ff-4f92-890c-b56153    schedule 05.05.2017