Должно работать следующее:
doc.Descendants().First()
.Select(x =>
{
testPlan.Name= x.Attribute("name").ToStringValue();
testPlan.DatabaseName = x.Attribute(DATABASE_ATTR)
.ToStringValue();
testPlan.LoginUsername = x.Attribute(USERNAME_ATTR)
.ToStringValue();
testPlan.LoginPassword = x.Attribute(PASSWORD_ATTR)
.ToStringValue();
testPlan.ApplicationSource = x.Attribute(APPSOURCE_ATTR)
.ToStringValue();
return testPlan;
})
.ToList();
Вызов First
в середине должен гарантировать, что только атрибуты первого потомка будут назначены свойствам testPlan
.ToList
в конце используется для реального выполнения кода внутри Select
.
Хотя это работает, я не рекомендую использовать его, потому что он использует LINQ так, как он не был создан для,Кроме того, его легко создать неправильно:
- Если вы забудете
First
, testPlan будет содержать значения атрибута элемента last в вашем XML, поскольку код выборавыполняется для каждого элемента и перезаписывает свойства. - Если вы забудете вызов
ToList
или аналогичного метода, который вызывает выполнение, код внутри Select
никогда не будет выполнен.
Итак, проблема в том, что вы создаете много возможностей для введения ошибки.
Я бы реализовал что-то вроде этого следующим образом:
var x = doc.Descendants.First();
testPlan.Name= x.Attribute("name").ToStringValue();
testPlan.DatabaseName = x.Attribute(DATABASE_ATTR).ToStringValue();
testPlan.LoginUsername = x.Attribute(USERNAME_ATTR).ToStringValue();
testPlan.LoginPassword = x.Attribute(PASSWORD_ATTR).ToStringValue();
testPlan.ApplicationSource = x.Attribute(APPSOURCE_ATTR).ToStringValue();
Это короче, легче для чтения и не нарушает LINQ, чтобы делать то, для чего он не был создан.