我有一个由Linq查询填充的数据网格。当datagrid中的焦点行发生更改时,我需要设置一个等于该对象中某个属性的变量。
我试过......
var selectedObject = view.GetRow(rowHandle);
_selectedId = selectedObject.Id;
...但编译器根本不关心这个(“嵌入式语句不能是声明或标注语句”)。
似乎该属性应该易于访问。在运行期间检查对象会显示我期望的所有属性,我只是不知道如何访问它们。
如何访问匿名对象的属性?
编辑澄清:
我碰巧使用DevExpress XtraGrid控件。我用Linq查询加载了这个控件,该查询由几个不同的对象组成,因此使得数据不符合我已经拥有的任何一个类(即,我无法将其转换为任何类)。
我正在使用.NET 3.5。
当我查看view.GetRow(rowHandle)方法的结果时,我得到一个如下所示的匿名类型:
{ ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 }
我的目标是从这个匿名类型获取ClientId,以便我可以做其他事情(例如加载包含该客户端记录的表单)。
我在早期的答案中尝试了一些建议,但无法达到我可以获得此ClientId的程度。
答案 0 :(得分:46)
你有没有试过用反射?这是一个示例代码段:
// use reflection to retrieve the values of the following anonymous type
var obj = new { ClientId = 7, ClientName = "ACME Inc.", Jobs = 5 };
System.Type type = obj.GetType();
int clientid = (int)type.GetProperty("ClientId").GetValue(obj, null);
string clientname = (string)type.GetProperty("ClientName").GetValue(obj, null);
// use the retrieved values for whatever you want...
答案 1 :(得分:18)
获取给定密钥的数据项值的通用解决方案
public static T GetValueFromAnonymousType<T>( object dataitem, string itemkey ) {
System.Type type = dataitem.GetType();
T itemvalue = (T)type.GetProperty(itemkey).GetValue(dataitem, null);
return itemvalue;
}
示例:
var dataitem = /* Some value here */;
bool ismember = TypeUtils.GetValueFromAnonymousType<bool>(dataitem, "IsMember");
答案 2 :(得分:17)
匿名类型的一个问题是在函数之间很难使用它们。没有办法“命名”匿名类型,因此在它们之间进行转换非常困难。这可以防止它们被用作元数据中出现的任何类型的类型表达式,并且是用户定义的。
我无法确切地说出您正在使用的API。但是,API不可能返回强类型的匿名类型,因此我对该对象的猜测是对象的类型。 C#3.0及更低版本不支持动态访问,因此即使在运行时可用,您也无法访问属性Id。
您需要执行以下操作之一才能解决此问题
修改强>
以下是关于如何进行黑客匿名类型转换的示例
public T AnonymousTypeCast<T>(object anonymous, T typeExpression) {
return (T)anonymous;
}
...
object obj = GetSomeAnonymousType();
var at = AnonymousTypeCast(obj, new { Name = String.Empty, Id = 0 });
它的hacky的原因是它很容易打破这个。例如,在最初创建匿名类型的方法中。如果我在该类型中添加另一个属性,则上面的代码将编译但在运行时失败。
答案 3 :(得分:14)
您可以使用动态类型在运行时访问匿名类型的属性,而无需使用反射。
var aType = new { id = 1, name = "Hello World!" };
//...
//...
dynamic x = aType;
Console.WriteLine(x.name); // Produces: Hello World!
在此处详细了解动态类型:http://msdn.microsoft.com/en-us/library/dd264736.aspx
答案 4 :(得分:3)
当我处理传递匿名类型并尝试重新编写它们时,我最终发现编写处理该对象的包装器更容易。这是关于它的博客文章的链接。
http://somewebguy.wordpress.com/2009/05/29/anonymous-types-round-two/
最终,您的代码看起来像这样。
//create an anonymous type
var something = new {
name = "Mark",
age = 50
};
AnonymousType type = new AnonymousType(something);
//then access values by their property name and type
type.With((string name, int age) => {
Console.Write("{0} :: {1}", name, age);
});
//or just single values
int value = type.Get<int>("age");
答案 5 :(得分:1)
正如JaredPar猜对错,GetRow()
的返回类型为object
。使用DevExpress网格时,您可以像这样提取所需的值:
int clientId = (int)gridView.GetRowCellValue(rowHandle, "ClientId");
这种方法有类似的缺点,比如之前描述的“hacky anonymous type casts”:你需要一个魔术字符串来识别列以及从object到int的类型转换。
答案 6 :(得分:1)
DevExpress的xtraGridView有一个像这样的方法GetRowCellDisplayText(int rowHandle,GridColumn列)。使用此方法,以下代码返回匿名类型的id。
var _selectedId = view.GetRowCellDisplayText(rowHandle, "Id");
虽然这不能解答“如何访问匿名对象的属性?”这一问题,但它仍然试图解决问题的根本原因。
我尝试使用devXpress版本11.1,我可以看到这个问题是在大约2。5年前首次提出的。可能问题的作者可能有一个解决方法或自己找到解决方案。然而,我仍然在回答,这可能对某人有所帮助。
答案 7 :(得分:0)
这可能是错误的(您可能没有足够的代码)但是您不需要索引到该行,以便您选择所需的列?或者,如果“Id”是您想要的列,您应该执行以下操作:
var selectedObject = view.GetRow(rowHandle);
_selectedId = selectedObject["Id"];
这就是我如何抓取数据网格中列的内容。现在,如果列本身是一个匿名类型,那么我不知道,但是如果你只是获得一个带有基本类型的命名列,那么这应该可行。
答案 8 :(得分:0)
希望这会有所帮助,我会传递一个接口列表,我需要从中获取一个不同的列表。首先,我得到一个匿名类型列表,然后我将它转移到我的对象列表。
private List<StockSymbolResult> GetDistinctSymbolList( List<ICommonFields> l )
{
var DistinctList = (
from a
in l
orderby a.Symbol
select new
{
a.Symbol,
a.StockID
} ).Distinct();
StockSymbolResult ssr;
List<StockSymbolResult> rl = new List<StockSymbolResult>();
foreach ( var i in DistinctList )
{
// Symbol is a string and StockID is an int.
ssr = new StockSymbolResult( i.Symbol, i.StockID );
rl.Add( ssr );
}
return rl;
}
答案 9 :(得分:0)
您可以循环遍历匿名类型的属性,如下所示:
var obj = new {someValue = "hello", otherValue = "world"};
foreach (var propertyInfo in obj.GetType().GetProperties() {
var name = propertyInfo.Name;
var value = propertyInfo.GetValue(obj, index: null);
...
}
答案 10 :(得分:0)
如果您知道自己在做什么,并且在代码更改时不担心会出现运行时错误,那么您可以将行数据转换为dynamic
:
var data = view.GetRow(rowHandle) as dynamic;
int clientId = data.ClientID;
string clientName = data.ClientName;
int jobs = data.Jobs
无编译时验证。但它应该很好用。
答案 11 :(得分:0)
var result = ((dynamic)DataGridView.Rows[rowNum].DataBoundItem).value;