使用LINQ投射一个投影列表会返回一个空值列表?

时间:2011-12-06 20:36:26

标签: c# linq linq-to-xml

当我尝试在BuildTypes方法中投射投影列表时,我得到一个空值列表。我也尝试过使用.Cast(),但是我得到一个错误,即某些属性无法转换。如果它有用,我可以发布错误。这是我的代码:

public class AuditActionType: EntityValueType
{
}

private List<T> BuildTypes<T>(XDocument xDocument) where T: EntityValueType
{
    var types = 
        (from ty in xDocument.Descendants("RECORD")
         select new
            {
                Id = GenerateGuid(),
                Name = ty.Element("Name").Value,
                EntityStatus = _activeEntityStatus,
                DateCreated = DateTime.Now,
                DateModified = DateTime.Now
            } as T).ToList();

    return types;
} 

所以我会这样称呼它:

var auditActorTypes = BuildTypes<AuditActorType>(auditActorTypesXml)

我需要从XML文件中提取大量类型,并且不想为每种类型重复代码。

3 个答案:

答案 0 :(得分:7)

您正在尝试将匿名对象转换为T类型,这是无法完成的。匿名类型是它自己的唯一类型,与传入的T无关。

相反,您可以在类型new()上提供T约束,以表示它需要默认构造函数,然后执行new T()而不是创建新的匿名类型:

private List<T> BuildTypes<T>(XDocument xDocument) where T: EntityValueType, new()
{
    var types = 
        (from ty in xDocument.Descendants("RECORD")
         select new T()
            {
                Id = GenerateGuid(),
                Name = ty.Element("Name").Value,
                EntityStatus = _activeEntityStatus,
                DateCreated = DateTime.Now,
                DateModified = DateTime.Now
            }).ToList();

    return types;
} 

当然,这是假设IdNameEntityStatusDateCreatedDateModified都是基础的所有属性{{1 }}

答案 1 :(得分:4)

您无法使用当前代码执行此操作,因为new { }会创建一个与T无关的anonymous type(它既不是子节点,也不是T类型)。您可以做的是在Id类上实施NameEntityStatusDateCreatedDateModifiedEntityValueType并更改:< / p>

private List<T> BuildTypes<T>(XDocument xDocument) where T: EntityValueType

要:

 private List<T> BuildTypes<T>(XDocument xDocument) where T: EntityValueType, new()

其中指定传递给我们方法的任何类型参数必须具有无参数构造函数,该构造函数允许通过更改实际构造T类型的对象:

select new { ... } as T

要:

select new T { ... }

最终结果:

public class EntityValueType
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    // Change this to the correct type, I was unable to determine the type from your code. 
    public string EntityStatus { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateModified { get; set; }
}

public class AuditActionType: EntityValueType
{
}

private List<T> BuildTypes<T>(XDocument xDocument) where T: EntityValueType, new()
{
    return (from ty in xDocument.Descendants("RECORD")
        select new T
            {
                Id = GenerateGuid(),
                Name = ty.Element("Name").Value,
                EntityStatus = _activeEntityStatus,
                DateCreated = DateTime.Now,
                DateModified = DateTime.Now
            }).ToList();
} 

答案 2 :(得分:1)

更改代码:

private List<T> BuildTypes<T>(XDocument xDocument) where T: EntityValueType, new()
{
    var types = 
        (from ty in xDocument.Descendants("RECORD")
         select new T()
            {
                Id = GenerateGuid(),
                Name = ty.Element("Name").Value,
                EntityStatus = _activeEntityStatus,
                DateCreated = DateTime.Now,
                DateModified = DateTime.Now
            }).ToList();

    return types;
}