Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 559
Gabriel Avatar asked Nov 01 '11 12:11

Gabriel


1 Answers

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;
}
like image 159
Michael Edenfield Avatar answered Sep 22 '22 17:09

Michael Edenfield