我正在尝试使用包含嵌套类数组的LINQ填充实例。我已设法使用以下LINQ执行此操作。我还在select中包含了构成实例的类。
select new EditableWarrantBook {
Id = p1.id,
Comment = p1.EntryComment,
WarrantYear1 = new BookYear {
StatusYear = p2.StatusYear,
Status = p2.Status,
},
WarrantYear2 = new BookYear {
StatusYear = p3.StatusYear,
Status = p3.Status,
},
WarrantYear3 = new BookYear {
StatusYear = p4.StatusYear,
Status = p4.Status,
}
}
public class EditableWarrantBook
{
public int Id { get; set; }
public string Comment { get; set; }
public BookYear[] WarrantYear = new BookYear[3];
public BookYear WarrantYear1
{
get { return WarrantYear[0]; }
set { WarrantYear[0] = value; }
}
public BookYear WarrantYear2
{
get { return WarrantYear[1]; }
set { WarrantYear[1] = value; }
}
public BookYear WarrantYear3
{
get { return WarrantYear[2]; }
set { WarrantYear[2] = value; }
}
}
public class BookYear
{
public int? StatusYear { get; set; }
public string Status { get; set; }
}
这有效我可以使用WarrantYear[0]
或WarrantYear1
访问值。在设计UI时,这有时很有用。但是,在这种情况下,我不需要WarrantYear1
属性,因为我将其转换为JSON并且我不需要重复(或者想要在网络上发送相同数据的两个版本)。我的问题是,如何编写select语句来加载WarrantYear数组。或者我如何编写类,以便我可以作为属性访问该数组。我的解决方案不应包含Warrant1, Warrant2, Warrant3
类中的EditableWarrantBook
属性。
答案 0 :(得分:1)
由于我无法在没有Warrant1,Warrant2和Warrant3属性的情况下让select工作,我将其原样保留并重写该类,以便JSON序列化程序创建一个没有Warrant1,Warrant2和Warrant3属性的JSON实例。我使用this文章的反思。为了澄清这个问题,我的第一次尝试是创建一个JSON有效负载,它的大小是原来的两倍,因为JSON序列化器同时创建了Warrant1,Warrant2和Warrant3结构以及Warrant []数组。使用JSON结果的基类重写类,只有Warrant []数组满足Webservice的接口要求。
namespace my.Models
{
public class WarrantBook
{
public int Id { get; set; }
public string Comment { get; set; }
BookYear[] warrantYear = new BookYear[3];
public BookYear[] WarrantYear
{
get { return warrantYear; }
set { warrantYear = value; }
}
}
public class EditableWarrantBook : WarrantBook
{
public BookYear WarrantYear1
{
get { return WarrantYear[0]; }
set { WarrantYear[0] = value; }
}
public BookYear WarrantYear2
{
get { return WarrantYear[1]; }
set { WarrantYear[1] = value; }
}
public BookYear WarrantYear3
{
get { return WarrantYear[2]; }
set { WarrantYear[2] = value; }
}
}
public class BookYear
{
public int? StatusYear { get; set; }
public string Status { get; set; }
}
public static class Ext
{
public static void CopyProperties(this EditableWarrantBook source, WarrantBook destination)
{
// Iterate the Properties of the destination instance and
// populate them from their source counterparts
PropertyInfo[] destinationProperties = destination.GetType().GetProperties();
foreach (PropertyInfo destinationPi in destinationProperties)
{
PropertyInfo sourcePi = source.GetType().GetProperty(destinationPi.Name);
destinationPi.SetValue(destination, sourcePi.GetValue(source, null), null);
}
}
}
}
用法WCF REST Web服务
[WebGet(UriTemplate = "GetWarrant?id={s}&user={user}")]
public WarrantBook GetWarrant(string s, string user)
{
int id;
if (int.TryParse(s, out id))
{
EditableWarrantBook model = SessionWarrantBook.One(p => p.Id == id);
model.CheckedOutBy = user; // need to add checkout code
WarrantBook jsonModel = new WarrantBook();
model.CopyProperties(jsonModel);
return jsonModel;
}
return new WarrantBook();
}
答案 1 :(得分:0)
问题在于您尝试将SQL世界(构建查询)与CLR世界(创建新对象)混合在一起。解决这个问题的方法是将查询分解为初始数据获取查询(SQL世界),然后枚举结果以转换为对象(CLR世界):
所以在where p1.SaleYear == 2009
之后,添加:
select new { p1, p2, p3, p4 })
.AsEnumerable()
.Select(tr => new EditableWarrantBook
{
Id = tr.p1.id,
Comment = tr.p1.EntryComment,
WarrantYear = new[] {
tr.p2 == null ? (BookYear)null : new BookYear // EDITED LINE
{
StatusYear = tr.p2.StatusYear,
Status = tr.p2.Status,
},
tr.p3 == null ? (BookYear)null : new BookYear // EDITED LINE
{
StatusYear = tr.p3.StatusYear,
Status = tr.p3.Status,
},
tr.p4 == null ? (BookYear)null : new BookYear // EDITED LINE
{
StatusYear = tr.p4.StatusYear,
Status = tr.p4.Status,
}}
}).ToList();
如果您想保留查询语法,只需将其更改为:
result = from tr in
(/*Select up to the AsEnumerable call above)*/).AsEnumerable()
select new EditableWarrantBook
{
/* Initialization code supplied above */
}
编辑:所以我再次修改了这个例子。它看起来像你要回来的值之一是null,所以我添加了一个空检查以确保你没有访问空对象的属性(虽然我没有检查p1
是否为null )。