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

У меня есть проект, в котором я должен разместить некоторый код на другом уровне, и из-за этого я должен передать запрос linq в метод. Этот код:

var HRPersonnelContactInfoTelService = App.Api.HRPersonnelContactInfoTelService.Instance().Data();
        var SMSGroupMemberService = App.Api.SMSGroupMemberService.Instance().Data();
        return (from x in SMSGroupMemberService
                where Recivers.Contains(x.GroupID)
                join v in HRPersonnelContactInfoTelService on x.Pers_Code equals v.Pers_Code
                select new { Pers_Code = (int)x.Pers_Code, Tel = v.Tel }).ToList();

Я преобразовал код в:

public dynamic HRPersonnelContactInfoTelMethod(List<int> Recivers)
    {
        var HRPersonnelContactInfoTelService = App.Api.HRPersonnelContactInfoTelService.Instance().Data();
        var SMSGroupMemberService = App.Api.SMSGroupMemberService.Instance().Data();
        return (from x in SMSGroupMemberService
                where Recivers.Contains(x.GroupID)
                join v in HRPersonnelContactInfoTelService on x.Pers_Code equals v.Pers_Code
                select new { Pers_Code = (int)x.Pers_Code, Tel = v.Tel }).ToList();
    }

но когда я использую его в foreach

Исключение типа «Microsoft.CSharp.RuntimeBinder.RuntimeBinderException» возникло в System.Core.dll, но не было обработано в пользовательском коде.

Дополнительная информация: «объект» не содержит определения для «Pers_Code».

Используйте это так:

var q = App.Api.HRPersonnelContactInfoTelService.Instance().HRPersonnelContactInfoTelMethod(Recivers);
        foreach (var item in Recivers)
        {
            var res = App.Api.SMSMessageGroupService.Instance().AddOrUpdate(null, MessageId, item);
        }
        foreach (var z in q)
        {
            string SendNumber = Number[1].Trim().Substring(0, 3) == "+98" ? Number[1].Trim() : "+98" + Number[1].Trim();
            var res = App.Api.SMSMessageLogService.Instance().AddOrUpdate(null, MessageId, (int)z.Pers_Code, z.Tel.ToString(),
                 0, int.Parse(ddlSMSWorkingGroups.SelectedValue.ToString()), (int)z.Pers_Code, SendNumber, 0);
            send.SendSMS("nazmaran", "qwerty", SendNumber, "09122596898", txtPredefinedRemarks.Text);
        }

person metro    schedule 08.09.2016    source источник
comment
добавьте немного кода о том, как вы его используете   -  person Mikhail Tulubaev    schedule 08.09.2016


Ответы (2)


Я бы никогда не использовал dynamic для возврата результата запроса linq, который использует анонимные типы для проецирования результатов. Вместо этого я бы создал класс, содержащий результаты:

public class SomeName
{
   public int Pers_Code { set; get; }
   public string /* Change to Correct Type */ Tel { set; get;}
}

Применение:

public List<SomeName> HRPersonnelContactInfoTelMethod(List<int> Recivers)
{
   var HRPersonnelContactInfoTelService = App.Api.HRPersonnelContactInfoTelService.Instance().Data();
   var SMSGroupMemberService = App.Api.SMSGroupMemberService.Instance().Data();
   return (from x in SMSGroupMemberService
           where Recivers.Contains(x.GroupID)
           join v in HRPersonnelContactInfoTelService on x.Pers_Code equals v.Pers_Code
           select new SomeName() { Pers_Code = (int)x.Pers_Code, Tel = v.Tel }).ToList();
}

Создание типа для хранения результатов — ничто по сравнению со сложностью используемой динамики.

person Zein Makki    schedule 08.09.2016
comment
Это не работает: невозможно неявно преобразовать тип «System.Collections.Generic.List‹‹анонимный тип: int Pers_Code, string Tel››» в «System.Collections.Generic.List‹App.Api.HRPersonnelContactInfoTelService.SomeName›» - person metro; 08.09.2016

Кажется, что .NET не может выполнять динамическую типизацию с помощью var и итератора через динамический, который представляет список объектов.

Итак, когда вы создаете переменную с var - .NET не может предсказать возвращаемый тип и создает новую переменную object, так как каждый тип наследуется от object.

Однако реализация возвращаемого типа как dynamic является плохой практикой — возможные ошибки не могут быть найдены до тех пор, пока вы не вызовете этот метод. Итак, реализуйте использование другого класса, как предложил @user3185569.

person Mikhail Tulubaev    schedule 08.09.2016