Как получить доступ к свойству count динамического типа в С# 4.0?

У меня есть следующий метод, который возвращает динамический объект, представляющий IEnumerable<'a> ('a=anonymous type):

    public dynamic GetReportFilesbyStoreProductID(int StoreProductID)
    {
        Report report = this.repository.GetReportByStoreProductID(StoreProductID);

        if (report == null || report.ReportFiles == null)
        {
            return null;
        }

        var query = from x in report.ReportFiles
                    orderby x.DisplayOrder
                    select new { ID = x.RptFileID, Description = x.LinkDescription, File = x.LinkPath, GroupDescription = x.ReportFileGroup.Description };

        return query;
    }

Я хочу иметь доступ к свойству Count этого IEnumerable анонимного типа. Я пытаюсь получить доступ к вышеуказанному методу, используя следующий код, и он терпит неудачу:

        dynamic Segments = Top20Controller.GetReportFilesbyStoreProductID(StoreProductID");

        if (Segments.Count == 0)  // <== Fails because object doesn't contain count.
        {
            ...
        }
  • Как работает ключевое слово dynamic?
  • Как я могу получить доступ к свойству Count анонимного типа IEnumerable?
  • Есть ли способ использовать этот анонимный тип или мне нужно создать пользовательский объект, чтобы я мог вернуть строго типизированный IEnumerable<myObject> вместо dynamic?

Я бы предпочел не делать этого, если могу, поскольку этот метод вызывается только в одном месте, и создание одноразового объекта кажется излишним.


person Rodney    schedule 08.06.2011    source источник
comment
Вам следует настоятельно рассмотреть возможность создания настоящих типов вместо анонимных и вернуть IEnumerable из них. Использование для этой цели динамического типа сводит на нет все преимущества статической типизации.   -  person Kirk Woll    schedule 09.06.2011
comment
@Kirk Отчеты могут быть динамическими? не совсем в этом случае, но все же   -  person Bas    schedule 09.06.2011
comment
Когда вы определяете одноразовый тип только для возврата из метода, у статической типизации очень мало преимуществ, если они вообще есть.   -  person mqp    schedule 09.06.2011
comment
@Kirk, этот пользовательский объект будет одноразовым объектом, который используется один раз. Есть ли лучший вариант, чем создание целого класса для одноразового использования?   -  person Chev    schedule 09.06.2011
comment
@Chevex, если OP возвращает это значение из метода public, я не понимаю, почему мы думаем, что он будет вызываться только один раз.   -  person Kirk Woll    schedule 09.06.2011
comment
@kirk, ну, у меня есть особое понимание, так как он мой коллега. Он будет вызван только один раз.   -  person Chev    schedule 09.06.2011
comment
@mquander, я совершенно не согласен с тем, что у статической типизации нет никаких преимуществ даже в разовых ситуациях. Если вы предполагаете, что было бы неплохо, если бы вы могли возвращать анонимные типы (как этот тип) из метода, я согласен! Но ты не можешь. И статическая типизация по-прежнему бесконечно полезна в этой ситуации. (intellisense, безопасность во время компиляции и т. д.)   -  person Kirk Woll    schedule 09.06.2011
comment
Должен согласиться с @Kirk здесь. Если бы этот метод был приватным, разумным было бы динамическое возвращение последовательности анонимных типов. Однако он публичный.   -  person TrueWill    schedule 09.06.2011
comment
@True, чтобы не спорить, но я не думаю, что dynamic следует когда-либо использовать для связывания анонимного типа. Его никогда не следует использовать, потому что слишком лениво создавать правильный тип. Его следует использовать для отражения, динамической отправки, COM или динамических сценариев.   -  person Kirk Woll    schedule 09.06.2011
comment
Если вы заметили, он не спрашивает, как его следует использовать. Он спрашивает, как использовать dynamic в этом случае. Неважно, правильный ли это выбор. Он, скорее всего, все равно наберет его статически, но ответ на вопрос все еще интересен.   -  person Chev    schedule 09.06.2011
comment
@Chevex, да, и поэтому это комментарии, а не ответы. :)   -  person Kirk Woll    schedule 09.06.2011
comment
Я нахожу необычным, что люди так придирчивы к тому, когда dynamic используется и не используется; Я отлично справляюсь с написанием Javascript, Clojure и т. д., где (удушье) все динамично! Однако я согласен с тем, что использование dynamic в этой ситуации не является идиоматическим. Я бы лично сделал одноразовый именованный тип или передвинул бы вещи, чтобы исключить необходимость этого делать.   -  person mqp    schedule 09.06.2011
comment
@mquander, по этой логике, почему бы не отказаться от var и именованных типов и использовать dynamic для каждого объявления типа, которое у вас есть?   -  person Kirk Woll    schedule 09.06.2011
comment
@Kirk - я столкнулся с одним сценарием, в котором это имеет смысл. У вас есть оператор LONG Linq-to-Objects, который использует анонимные типы для соединений (из-за равенства свойств). Вы хотите реорганизовать это, но не можете извлечь метод из-за анонимных типов. Вам нужно будет не только создать класс, но и переопределить Equals и GetHashCode.   -  person TrueWill    schedule 09.06.2011
comment
@Kirk: Потому что полученный в результате язык C# без типов будет отстойным по сравнению с другими современными динамическими языками, и я подозреваю, что он также будет плохо работать в сравнении. Однако на самом деле это не является аргументом против изолированного использования dynamic для обхода неудобных битов C#.   -  person mqp    schedule 09.06.2011


Ответы (5)


IEnumerable<T>, возвращаемое этим методом, не имеет свойства Count, поэтому я не понимаю, о чем вы говорите. Может быть, вы забыли написать ToList() в конце, чтобы преобразовать его в список, или вы хотели вызвать метод Count() для IEnumerable<T>?

person mqp    schedule 08.06.2011
comment
Статического свойства Count может и не быть, но есть расширение Count() LINQ. Я думаю, что его точка зрения в том, что он не знает, как использовать динамический объект, который возвращается. - person Chev; 09.06.2011
comment
Что ж, он использовал бы его правильно, если бы имел в виду реально существующее свойство или метод, так что он, должно быть, просто что-то перепутал. - person mqp; 09.06.2011
comment
Ах да, я сообщу ему, чтобы он добавил скобки к вызову Count. - person Chev; 09.06.2011

Вам нужно будет явно вызвать Enumerable.Count().

IEnumerable<string> segments =
  from x in new List<string> { "one", "two" } select x;

Console.WriteLine(segments.Count());  // works

dynamic dSegments = segments;

// Console.WriteLine(dSegments.Count());  // fails

Console.WriteLine(Enumerable.Count(dSegments));  // works

См. метод расширения и динамический объект в c# для обсуждения того, почему расширение методы не поддерживаются динамической типизацией.

(Префикс "d" используется только в примере кода — пожалуйста, не используйте венгерскую нотацию!)

Обновление: Лично я бы выбрал @Magnus answer использует if (!Segments.Any()) и возвращает IEnumerable<dynamic>.

person TrueWill    schedule 08.06.2011
comment
+1 Совсем забыл про соображения при использовании Dynamics. Действительно интересно, как сработал принятый ответ. Спасибо хоть - person iam.Carrot; 21.04.2017
comment
идеально.. +++++++ - person Thameem; 24.07.2019

Count() необходимо перечислить для завершения коллекции, вы, вероятно, захотите:

if (!Segments.Any()) 
{
}

И ваша функция должна возвращать IEnumerable<object> вместо динамического

person Magnus    schedule 08.06.2011
comment
+1 - я должен был попробовать, но это работает. Хотя я подозреваю, что OP захочет вернуть IEnumerable‹dynamic›, чтобы получить свойства анонимного типа. - person TrueWill; 09.06.2011

Попробуйте Linq countusing System.Linq; Segments.Count()

person Bas    schedule 08.06.2011

Вы также можете использовать свойство Length!

if (!Segments.Length)
{
    `enter code here`
}
person alvescleiton    schedule 31.07.2019