C # Анонимный доступ к типу из другого метода

#c# #linq #anonymous-types

#c# #linq #анонимные типы

Вопрос:

у меня есть поле со списком, где заполняется с использованием коллекций анонимного типа:

 var results = (from row in data.Tables[0].AsEnumerable()
               select new { 
                    Id = row.Field<int>("id"),
                    Name = row.Field<string>("Name
               }).Distinct();

myComboBox.ValueMember = "Id";
myComboBox.DisplayMember = "Name";

foreach (var n in results)
{
    myComboBox.Items.Add(n);
}
 

Затем в методе SelectedIndexChanged выпадающего списка я хочу получить идентификатор выбранного элемента, но я не могу получить доступ к свойству «Id» в myComboBox.SelectedItem — это выбранный объект.

 private void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    if (myComboBox.SelectedItem != null)
    {
        var x = myComboBox.SelectedItem;

            ¿¿¿ ???
    }  
}
 

Есть идеи?

Комментарии:

1. если вам просто нужен идентификатор, вы можете использовать myCombobox. Выбранное значение?

2. Ключевое слово dynamic доставит вам неприятности. Члены анонимного типа имеют внутреннюю доступность. Или, другими словами, вы не можете получить к ним доступ, когда ваш код пользовательского интерфейса находится в отдельной сборке. Что очень распространено, отделение пользовательского интерфейса от модели данных является достойным продолжением. Просто не используйте анонимный тип здесь.

3. Использование анонимных и / или динамических типов здесь не является ответом. Что не так с вашим собственным облегченным типом? (Или, для этого конкретного примера, KeyValuePair<int,string> ?)

4. Или используйте Tuple<int, string> , что является более общим назначением, чем KeyValuePair .

Ответ №1:

Поскольку вы используете Id в качестве значения, идентификатор будет сохранен как myComboBox.Выбранный элемент.Значение

Ответ №2:

Вы тоже можете использовать отражение.

 private void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
    if (myComboBox.SelectedItem != null)
    {
        var x = myComboBox.SelectedItem;
        System.Type type = x.GetType();
        int id = (int)type.GetProperty("Id").GetValue(obj, null);
    }  
}
 

Комментарии:

1. Трюк с приведением типов намного быстрее, чем отражение, хотя я не могу сказать, какой из них с большей вероятностью продолжит работать в будущих версиях C # / CLR.

Ответ №3:

Сегодня утром я прочитал статью, в которой объяснялось именно это:

http://blog.filipekberg.se/2011/10/06/playing-with-anonymous-types-in-c/

Идея в том, что вам нужно вернуть «динамический» тип.

 dynamic GetAnonymousType()
{
    var person = new { Name = "Filip" };
    return person;
}
 

Ответ №4:

если вы работаете с C # 4.0, используйте ключевое слово dynamic, в противном случае определите класс, который содержит идентификатор и имя, вместо использования анонимного типа, или используйте отражение.

Ответ №5:

Вам нужно самое простое решение? Создайте класс с именем SimpleEntity с тремя полями: Id, Description и Tag. У этого класса должен быть конструктор, который принимает объект, и, используя отражение, вы получаете Id и Name и устанавливаете два поля. И вы также устанавливаете свойство тега с объектом. Таким образом, вам просто нужно заполнить комбинацию, используя этот новый класс, а затем вы получите обратно исходный объект. Надеюсь, это поможет.

Комментарии:

1. Вы можете избежать отражения, если конструктор принимает три параметра (int, string, object)

Ответ №6:

Я думаю, вам было бы лучше использовать что-то вроде Tuple<int, string> here, а не анонимный тип, но можно делать то, что вы хотите. Два анонимных типа в одной сборке, которые имеют одинаковые имена полей и типы полей в одном и том же порядке, внутренне «сворачиваются» в один тип. Вы можете использовать это, чтобы передавать экземпляры анонимного типа и, используя общий вывод типа, приводить их к типу позже.

Обратите внимание, что это зависит от внутреннего механизма в компиляторе C #, поэтому нет гарантии, что он продолжит работать; однако он работает во всех текущих версиях C #, которые имеют анонимные типы.

Обновление: на самом деле это явно вызывается в спецификации C #, поэтому это должно быть абсолютно безопасно:

В рамках одной и той же программы два анонимных инициализатора объектов, которые задают последовательность свойств с одинаковыми именами и типами в том же порядке, будут создавать экземпляры одного и того же анонимного типа

Также обратите внимание, что это работает только в пределах одной сборки (не позволяйте ссылке спецификации на «программу» сбивать вас с толку). Для использования анонимных типов из другой сборки требуется отражение (и, IMO, это, как правило, очень плохая идея.) Однако для сценариев привязки данных, таких как ваш, это работает нормально.

 public object foo; 

public void Create()
{
  this.foo = new { Id = 1, Name = "Melvin" };
}

public void Consume()
{
  var x = new { Id = 0, Name = String.Empty };
  var y = this.Cast(this.foo, x);
}

public T Cast<T> ( object o, T template )
{
  return (T)o;
}
 

Комментарии:

1. Я удивлен, что этот ответ не получил больше любви — я думаю, это фантастика! Спасибо.

Ответ №7:

Вы можете использовать dynamic ключевое слово вместо var .