Gabriel
Gabriel

Reputation: 969

C# Anonymous Type access from other method

i've a ComboBox where is filled using a Collections of Anonymous Type:

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);
}

Then, in SelectedIndexChanged method of the comboBox, i want to retrieve the Id of the selected item, but i can't access to the "Id" property, in myComboBox.SelectedItem is the selected object.

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

            ¿¿¿ ???
    }  
}

Any ideas?

Upvotes: 9

Views: 2489

Answers (7)

Michael Edenfield
Michael Edenfield

Reputation: 28338

I think you would be better off using something like a Tuple<int, string> here, not an anonymous type, but it is possible to do what you want. Two anonymous types in the same assembly that have the same field names and field types in the same order are internally "folded" into a single type. You can use this to pass anonymous type instances around and, using generic type inference, typecast them at a later date.

Note that this relies on an internal mechanism in the C# compiler, so there's no guarantee it will continue to work; it works, however, in every current version of C# that has anonymous types.

Update: This is actually called out explicitly in the C# spec, so this should be completely safe to do:

Within the same program, two anonymous object initializers that specify a sequence of properties of the same names and types in the same order will produce instances of the same anonymous type

Note also that this only works within a single assembly (don't let the spec's reference to a "program" confuse you). To consume anonymous types from another assembly requires reflection (and, IMO, is generally a very bad idea.) However, for data binding scenarios such as yours, it works fine.

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;
}

Upvotes: 1

Francisco Goldenstein
Francisco Goldenstein

Reputation: 13767

Do you need the simplest solution? Create a class called SimpleEntity with three fields: Id, Description and Tag. This class should have a constructor that accept an Object and, using reflection, you get Id and Name and set the two fields. And you alse set the Tag property with the Object. In this way, you just need to populate the combo using this new class and then you get back the original object. I hope it helps.

Upvotes: 1

Agustin Meriles
Agustin Meriles

Reputation: 4854

You can use reflection too.

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);
    }  
}

Upvotes: 4

ojlovecd
ojlovecd

Reputation: 4892

if you are working with C# 4.0, then use dynamic keyword, otherwise, define a class which contains id and name instead of using anonymous type, or use reflection.

Upvotes: 1

javros
javros

Reputation: 823

You can use dynamic keyword instead of var.

Upvotes: 0

Jonas B
Jonas B

Reputation: 2391

Since you use Id as valuemember the Id would be stored as myComboBox.SelectedItem.Value

Upvotes: 9

jgallant
jgallant

Reputation: 11273

I read an article this morning that explained exactly this:

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

The idea is that you need to return a "dynamic" type.

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

Upvotes: 3

Related Questions