[英]Get fields from anonymous type
我有这个课:
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}
}
在我的WinForm中,使用以下功能:
private void QuantityToolStripMenuItem_Click(object sender, EventArgs e)
{
ServiceStock sstock = new ServiceStock();
var q = sstock.stockEtatQty().ToList();// q is a list<object>
string str = "";
foreach (var item in q)
{
str += item + Environment.NewLine;
}
MessageBox.Show(str);
}
结果是:
{ EAN = 1, Title = CSharp Security, Quantity = 970 }
{ EAN = 2, Title = MISC, Quantity = 100 }
...
我想要的是?
我不喜欢上面的结果,但是在foreach
循环中将item
每个字段分开,例如get item.EAN
, item.Title
和item.Quantity
。
如果无法解决我的问题,我想知道一个替代方法,
感谢帮助。
显而易见的解决方案是创建一个自定义类型(我们将其称为BookInfo
)并返回IEnumerable<BookInfo>
而不是IEnumerable<object>
(如果要将格式本身放入此类,则可以覆盖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);
}
由于在退出stockEtatQty()
方法时,有关匿名类型对象的静态类型信息已丢失,因此可以将对象转换为dynamic
字段,并按如下方式访问字段:
str = string.Join(Environment.NewLine, q.Cast<dynamic>().Select(item =>
string.Format("{0} {1} {2}", item.EAN, item.Title, item.Quantity)
));
强制转换为dynamic
告诉编译器EAN
, Title
和Quantity
需要在运行时解析。
请注意,我还用对string.Join
的调用替换了foreach
循环以提高性能:重复的字符串串联会创建不必要的部分字符串对象,而string.Join
避免了。 另一个解决方案是使用StringBuider
代替字符串串联+=
。
stockEtatQty
在一个项目中(服务),QuantityToolStripMenuItem_Click
在另一个项目中(视图)
不幸的是,这意味着您将无法使用匿名类型:匿名类型是在内部可见的情况下生成的,将它们的使用限制在生成它们的程序集中。 您可以根据此答案中所述的ExpandoObject
使用解决方法:
var q = afList.Select(x => {
dynamic res = new ExpandoObject();
res.EAN=x.EAN;
res.Title=x.title;
res.Quantity=x.qty;
return res;
});
您可以使用动态对象的集合代替简单对象作为方法的返回类型:
public IEnumerable<dynamic> stockEtatQty()
然后,您将没有IntelliSense,但会在运行时找到属性:
foreach (var item in sstock.stockEtatQty())
str += String.Format("{0}", item.EAN) + Environment.NewLine;
但是我建议您使用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());
创建一个表示新对象结构的新类,然后将其返回。
var q = from x in afList
select new SmallerType { EAN=x.EAN, Title=x.title, Quantity=x.qty };
WinForm函数
foreach (SmallerType item in q)
{
//
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.