C# 从匿名类型获取字段

C# 从匿名类型获取字段,c#,anonymous-types,C#,Anonymous Types,我有这门课: public class allFields { public string EAN { get; set; } public string title { get; set; } public string qty { get; set; } public string price { get; set; } public DateTime date { get; set; } } 以及一个返回匿名类型的函数: public IEnume

我有这门课:

public class allFields
{
    public string EAN { get; set; }
    public string title { get; set; }
    public string qty { get; set; }
    public string price { get; set; }
    public DateTime date { get; set; }
}
以及一个返回匿名类型的函数:

public IEnumerable<object> stockEtatQty()
{   
    List<allFields> afList = new List<allFields>();

    var query = from x in ctx.book
                where x.qty > 0
                select x;
    foreach (var item in query)
    {
        allFields af = new allFields();
        af.EAN = item.EAN;
        af.title = item.Titre;
        af.qty = ""+item.Quantite;
        afList.Add(af);
    }
    var q = from x in afList
            select new { EAN=x.EAN, Title=x.title, Quantity=x.qty };

    return q; //q is a IEnumerable<'a> where a is new {string EAN, string Title, string Quantity}
}
我想要什么?
我不希望像上面的结果那样,而是将循环
foreach
项的每个字段分开,例如get
item.EAN
item.Title
item.Quantity

如果我的问题没有解决方案,我想知道一个替代方案,

谢谢您的帮助。

您可以使用动态对象集合而不是简单对象作为方法的返回类型:

public IEnumerable<dynamic> stockEtatQty()
但我建议您使用EAN、Title和Quantity属性创建自定义类。或者只使用您的
allFields
,而不是匿名对象


还应考虑使用StringBuilder创建字符串,以避免在内存中创建大量字符串:

var builder = new StringBuilder();
foreach (var item in sstock.stockEtatQty())
   builder.AppendFormat("{0}{1}", item.EAN, Environment.NewLine);

MessageBox.Show(builder.ToString());

显而易见的解决方案是创建一个自定义类型(我们称之为
BookInfo
),并返回一个
IEnumerable
,而不是
IEnumerable
(如果您想将格式放入这个类本身,可以重写
ToString

然后您可以轻松地格式化输出

public class BookInfo
{
    public string EAN {get;set;}
    public string Title {get;set;}
    public int Quantity {get;set;}
}

public IEnumerable<BookInfo> stockEtatQty()
{   
    ...

    var q = from x in afList
            select new BookInfo { EAN=x.EAN, Title=x.title, Quantity=x.qty };

    return q;
}

private void QuantityToolStripMenuItem_Click(object sender, EventArgs e)
{
    ServiceStock sstock = new ServiceStock();
    var q = sstock.stockEtatQty();

    var message = string.Join(Environment.NewLine, 
                              q.Select(item => String.Format("{0} {1} {2}", item.EAN, item.Title, item.Quantity)));
    MessageBox.Show(message);
}
公共类图书信息
{
公共字符串EAN{get;set;}
公共字符串标题{get;set;}
公共整数数量{get;set;}
}
公共IEnumerable StocketTQty()
{   
...
var q=从afList中的x开始
选择new BookInfo{EAN=x.EAN,Title=x.Title,Quantity=x.qty};
返回q;
}
私有void QuantityToolStripMenuItem\u单击(对象发送方,事件参数e)
{
ServiceStock sstock=新ServiceStock();
var q=sstock.stockettqty();
var message=string.Join(Environment.NewLine,
q、 选择(item=>String.Format(“{0}{1}{2}”、item.EAN、item.Title、item.Quantity));
MessageBox.Show(message);
}

由于在退出
stockettqty()
方法时,有关匿名类型对象的静态类型信息丢失,因此可以将对象强制转换为
动态
并访问如下字段:

str = string.Join(Environment.NewLine, q.Cast<dynamic>().Select(item => 
    string.Format("{0} {1} {2}", item.EAN, item.Title, item.Quantity)
));

创建一个表示新对象结构的新类,并返回该类

var q = from x in afList
        select new SmallerType { EAN=x.EAN, Title=x.title, Quantity=x.qty };
WinForm函数

foreach (SmallerType item in q)
{
  //
}

我很难通过
公共类allFields
。请仔细阅读如何选择好的类名。我尝试了您的解决方案,但出现了以下错误:“object”不包含“EAN”的定义@user3757742您应该使用与匿名对象的属性完全相同的名称。另外,我认为您还没有修改方法的返回类型。我将返回类型从IEnumerable修改为IEnumerable,并且我将相同的名称作为匿名对象的属性,但仍然给我相同的名称error@user3757742对不起,不应该。如果所有操作都正确,则应该获得属性值(将在运行时进行计算)。我尝试了您的解决方案,但在生成时出现此错误:“System.Data.EnumerableRowCollectionExtensions.Cast(System.Data.EnumerableRowCollection)”是一个“方法”,在给定的context@user3757742请查看修复-我的代码缺少一对括号。现在我有一个错误:“object”不包含“EAN”的定义@user3757742我只是在本地运行了这个,并获得了我期望得到的结果。很可能,
stockettqty()
是否是来自与
QuantityToolStripMenuItem\u Click
不同项目的类的成员?我问的原因是匿名类是内部的。是的,
stockettqty()
在一个项目(服务)中,
QuantityToolStripMenuItem\u Click
在另一个项目(视图)@dasblinkenlight实际上我有5个以上的函数,它们与
stockettqty
的功能相同,但它们返回的结果不同,例如,我有另一个函数
stockettprice
返回EAN、Title和Price(而不是Quantity),还有另一个函数
stockettDate
返回日期(而不是Quantity或Price)@user3757742您是否总是将数据转换成字符串(在这种情况下,所有方法都可以返回格式化的字符串)或者他们有时会对数据做其他事情吗?请记住,如果有许多相似的方法都返回相似但不同的内容,那么使用不同的类型就更为重要。它确保编译器在那里验证您是否正确执行了所有操作,而不是编译器无法验证的容易出错的解决方案。
str = string.Join(Environment.NewLine, q.Cast<dynamic>().Select(item => 
    string.Format("{0} {1} {2}", item.EAN, item.Title, item.Quantity)
));
var q = afList.Select(x => {
    dynamic res = new ExpandoObject();
    res.EAN=x.EAN;
    res.Title=x.title;
    res.Quantity=x.qty;
    return res;
});
var q = from x in afList
        select new SmallerType { EAN=x.EAN, Title=x.title, Quantity=x.qty };
foreach (SmallerType item in q)
{
  //
}