System.InvalidCastException при приведении типа объекта к пользовательскому классу - PullRequest
0 голосов
/ 30 апреля 2018

Сегодня, работая над своим кодом, я натолкнулся на фазу, когда мне нужно было привести тип объекта к своему пользовательскому классу, который должен был быть очень простым, но я потратил часы на разрешение System.InvalidCastException, в конце концов я использовал JsonConvert чтобы сделать работу.

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

Приведена структура моего пользовательского класса

using SQLite.Net.Attributes;
namespace DataContract
{
public class Event
{
    #region Properties
    [PrimaryKey]
    public int Id { get; set; }

    public string Name { get; set; }

    public DateTime EventDateTime { get; set; }

    #endregion
}
}

Класс Event находится внутри общего проекта DataContract, и моя структура папок проекта приведена ниже,

Solution structure

Используя EntityFramework, я получаю List<Event> из своей базы данных sqlite, и я использую этот список для отображения элементов в моем табличном представлении для Android, я просматриваю один элемент за раз в своем списке и пытаюсь привести его к своему собственному Класс мероприятия.

Приведен код для того же, который я пробовал

//tableItems is my IList<object>
var item = tableItems[position];

        var view = convertView;
        if (view == null)
        {
            view = context.LayoutInflater.Inflate(Resource.Layout.NativeAndroidEventCell, null);
        }


        if (item.GetType().FullName.Equals("DataContract.Event"))
        {
                  var x = item as DataContract.Event; // returns null
                  var y = (DataContract.Event)item; // cast exception
                var z = item.GetType().GetField("Name"); // returns null    

        }

Исключение, которое я получаю, приведено на изображении, я не вижу здесь трассировку стека, так как она показывает ноль

enter image description here

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

enter image description here

В качестве последнего средства я использовал класс JsonConvert и сделал что-то вроде этого

if (item.GetType().FullName.Equals("DataContract.Event"))
        {
           //Not sure if this is the right approach here but it works
            var serializedObject = JsonConvert.SerializeObject(item, Formatting.Indented);
            var deserializedObject = JsonConvert.DeserializeObject<DataContract.Event>(x);

            view.FindViewById<TextView>(Resource.Id.textView1).Text = deserializedObject.Name;
            view.FindViewById<TextView>(Resource.Id.textView2).Text = deserializedObject.EventDateTime.ToString();
        }

JsonConvert работает, и я могу решить свою проблему, но я больше обращаю внимание на то, могу ли я узнать, мог ли я решить эту проблему лучше, чем с помощью JsonConvert, или то, что я сделал, было правильно. Пожалуйста, предложите

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

После долгих часов исследований я использовал свой собственный подход JSONSerialization для обработки приведений, как упомянуто в вопросе

var serializedObject = JsonConvert.SerializeObject(item, Formatting.Indented);
            var deserializedObject = JsonConvert.DeserializeObject<DataContract.Event>(x);

            view.FindViewById<TextView>(Resource.Id.textView1).Text = deserializedObject.Name;
            view.FindViewById<TextView>(Resource.Id.textView2).Text = deserializedObject.EventDateTime.ToString();
0 голосов
/ 30 апреля 2018

На самом деле, после прочтения этого несколько раз и некоторой догадки, вот ваша проблема.

Класс Event, который вы объявляете ниже, например,

List<Event> tableItems ...

означает "не", указывая на тот же класс, что и при попытке разыграть здесь

(DataContract.Event)item;

Это может быть подтверждено щелчком правой кнопкой мыши по обоим типам и выбором перехода к определению, возможно, это разные места.

Скорее всего, причина

  1. Один из них - сгенерированный прокси (если он поступает из WCF или по сети), другой - конкретный класс
  2. Другая вероятная причина: у вас разные версии одной и той же сборки, в которой они живут. Проверьте ваши ссылки

Также попробуйте разбить код на точку и определить, действительно ли эти типы указывают на одно и то же место. Это проблема, и вам нужно как-то ее исправить.

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

...