LINQ to XML转换为POCO对象

3
我有一个XML文件,想将其转换为POCO对象列表。
我有以下代码可以读取XML并从中创建对象。我只是想确认这是一个好的方法来完成这个任务,而且没有漏掉任何技巧。特别是关于嵌套的Linq查询。
XDocument xmlDoc = XDocument.Load(path);
var q = from file in xmlDoc.Descendants("File")
        select new ImportDefinition()
        {
            Name = file.Attribute("Name").Value,
            TypeName = file.Attribute("TypeName").Value,
            ColumnMappings =  
            (
                from map in file.Descendants("ColumnMap") 
                select new ColumnMap() 
                { 
                    DatabaseColumn = new Column()
                    { 
                        Name = map.Element("DatabaseColumn").Attribute("Name").Value
                    }
                }
            ).ToList<ColumnMap>()               
        };
List<ImportDefinition> def = q.ToList<ImportDefinition>();

谢谢

2个回答

3
如果您的POCO对象不仅具有字符串属性,XElement和XAttribute还提供了广泛的转换运算符以进行其他类型的转换,包括对空值的处理,以防元素/属性不存在。

示例:

XDocument xmlDoc = XDocument.Load(path);
var q = from file in xmlDoc.Descendants("File")
        select new ImportDefinition()
        {
            Name         = (string)file.Attribute("Name"),
            TypeName     = (string)file.Attribute("TypeName"),
            Size         = (int)file.Attribute("Size"),
            LastModified = (DateTime?)file.Attribute("LastModified"),
            // ...
        };

3
也许尝试显式转换。
public class ColumnMap
{
    public static explicit operator ColumnMap(XElement xElem)
    {
        return new ColumnMap()
        {
            DatabaseColumn = new Column()
            {
                Name = xElem.Element("DatabaseColumn").Attribute("Name").Value
            }
        };
    }
}

public class ImportDefinition
{
    public static explicit operator ImportDefinition(XElement xElem)
    {
        return new ImportDefinition() 
        { 
            Name           = (string)xElem.Attribute("Name"), 
            TypeName       = (string)xElem.Attribute("TypeName"), 
            Size           = (int)xElem.Attribute("Size"), 
            LastModified   = (DateTime?)xElem.Attribute("LastModified"), 
            ColumnMappings = xElem.Descendants("ColumnMap").Select(xelem => (ColumnMap)xelem).ToList()
        }; 
    }
}

然后像这样使用它:
XDocument xmlDoc = XDocument.Load(path); 
List<ImportDefinition> importDefinitions = xmlDoc.Descendants("File").Select(xElem => (ImportDefinition)xElem).ToList()

据我所知,.Cast<> 不会调用自定义转换运算符 - 或者它会吗? - dtb
@dtb:如果不是这样,那么这个程序就无法工作。虽然没有测试过,但我认为它只是一个扩展,类似于IEnumerable<U> Cast<T,U>(IEnumerable<T> targets) { foreach(T target in targets) yield return (U)target; } - Jimmy Hoffa
1
我相信这正是Enumerable.Cast所做的事情,并且由于将类型转换为泛型参数U,它可能不会很好地工作,因为据我所知它不会寻找自定义转换算子。但是我也没有测试过。 - dtb
@dtb:咬紧牙关测试了一下,你是对的,它没有寻找自定义转换运算符,但 select 方法完美地工作了。很奇怪,我想不到通用间接会这样做.. - Jimmy Hoffa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接