C # доступ анонимного типа из другого метода - PullRequest
9 голосов
/ 01 ноября 2011

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

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 comboBox я хочу получить Id выбранного элемента, но не могу получить доступ к свойству Id, в myComboBox. SelectedItem - выбранный объект.

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

            ¿¿¿ ???
    }  
}

Есть идеи?

Ответы [ 7 ]

9 голосов
/ 01 ноября 2011

Поскольку вы используете Id в качестве значенияМемера, он будет сохранен как myComboBox.SelectedItem.Value

4 голосов
/ 01 ноября 2011

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

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);
    }  
}
3 голосов
/ 01 ноября 2011

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

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

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

dynamic GetAnonymousType()
{
    var person = new { Name = "Filip" };
    return person;
}
1 голос
/ 01 ноября 2011

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

1 голос
/ 01 ноября 2011

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

0 голосов
/ 01 ноября 2011

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

Обратите внимание, что это зависит от внутреннего механизма в компиляторе 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;
}
0 голосов
/ 01 ноября 2011

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

...