从其他方法访问C#匿名类型

时间:2011-11-01 12:42:24

标签: c# linq anonymous-types

我有一个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);
}

然后,在comboBox的SelectedIndexChanged方法中,我想要检索所选项的Id,但我无法访问“Id”属性,在myComboBox中.SelectedItem是所选对象。

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

            ¿¿¿ ???
    }  
}

有什么想法吗?

7 个答案:

答案 0 :(得分:9)

由于您使用Id作为值成员,因此Id将存储为myComboBox.SelectedItem.Value

答案 1 :(得分:4)

您也可以使用反射。

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

答案 2 :(得分:3)

我今天早上读了一篇文章解释了这个:

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

这个想法是你需要返回一个“动态”类型。

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

答案 3 :(得分:1)

如果你正在使用C#4.0,那么使用dynamic关键字,否则,定义一个包含id和name而不是使用匿名类型的类,或者使用反射。

答案 4 :(得分:1)

您需要最简单的解决方案吗?创建一个名为SimpleEntity的类,其中包含三个字段:Id,Description和Tag。这个类应该有一个接受Object的构造函数,使用反射,你得到Id和Name并设置两个字段。您还可以使用Object设置Tag属性。这样,您只需要使用这个新类填充组合,然后返回原始对象。 我希望它有所帮助。

答案 5 :(得分:0)

您可以使用dynamic关键字代替var

答案 6 :(得分:0)

我认为你最好在这里使用像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;
}