2011-11-01 93 views
9

C#匿名类型的访问,我在那里用匿名类型的集合填充组合框:其他方法

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项,但我无法访问“Id”属性,在myComboBox.SelectedItem中是选定的对象。

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

      ¿¿¿ ??? 
    } 
} 

任何想法?

+0

如果你只是需要的ID你可以使用myCombobox.SelectedValue? – saus

+2

* dynamic *关键字会让你陷入困境。匿名类型的成员具有*内部*可访问性。换句话说,当您的UI代码位于单独的程序集中时,您无法访问它们。这是非常普遍的,将UI与数据模型分离是一种值得追求的方式。这里不要使用匿名类型。 –

+0

使用匿名和/或动态类型不是这里的答案。你自己的轻量级类型有什么问题? (或者,对于此特定示例,['KeyValuePair '](http://msdn.microsoft.com/en-us/library/5tbh8a42.aspx)?) – LukeH

回答

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

类型转换技巧比反射速度快得多,但我不能说哪个更有可能继续在未来版本的C#/ CLR中工作。 –

9

由于您使用的ID作为valuemember的标识将被存储为myComboBox.SelectedItem.Value

0

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

1

如果您使用的是C#4.0,那么使用动态关键字,否则,请定义一个包含id和名称的类,而不是使用匿名类型或使用反射。

1

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

+0

如果构造函数接受三个参数(int,string,object),则可以避免反射, –

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