Вы можете написать небольшой рекурсивный метод, чтобы справиться с этим:
IEnumerable<XElement> GetChildren ( string rootType, List<Parameter> parameters )
{
return from p in parameters
where p.ParentType == rootType
let children = GetChildren ( p.Type, parameters )
select children.Count() == 0 ?
new XElement ( p.Name, p.Type ) :
new XElement ( p.Name, children );
}
Каждый вызов создает Enumerable из XElements , который содержит параметры, чей родитель имеет переданный тип.Выбор повторяется в методе, снова находя дочерние элементы для каждого элемента.
Обратите внимание, что это предполагает, что данные сформированы правильно.Если два параметра имеют друг друга в качестве родителя, вы получите переполнение стека.
Волшебство заключается в классе XElements (Linq to Xml), который принимает перечисляемые элементы XElements для построения дерева, подобного структуре Xml.
При первом вызове передайте значение null (или используйте параметры по умолчанию, если используете C # 4) в качестве rootType.Используйте как:
void Main()
{
var parameters = new List<Parameter> {
new Parameter {Name = "composite", Type = "CompositeType" },
new Parameter {Name = "isThisTest", Type = "boolean" },
new Parameter {Name = "BoolValue", Type = "boolean", ParentType = "CompositeType" },
new Parameter {Name = "StringValue", Type = "string", ParentType = "CompositeType" },
new Parameter {Name = "AnotherType", Type = "AnotherCompositeType", ParentType = "CompositeType" },
new Parameter {Name = "account", Type = "string", ParentType = "AnotherCompositeType" },
new Parameter {Name = "startdate", Type = "date", ParentType = "AnotherCompositeType" }
};
foreach ( var r in GetChildren ( null, parameters ) )
{
Console.WriteLine ( r );
}
}
Вывод:
<composite>
<BoolValue>boolean</BoolValue>
<StringValue>string</StringValue>
<AnotherType>
<account>string</account>
<startdate>date</startdate>
</AnotherType>
</composite>
<isThisTest>boolean</isThisTest>
Редактировать
В ответ на ваш комментарий XElement дает вам две возможности для вывода в видестрока.
ToString () будет выводить форматированный Xml.
ToString (SaveOptions) позволяет указать форматированный или неотформатированный вывод, а такжеисключение повторяющихся пространств имен.
Я уверен, что вы, вероятно, могли бы адаптировать решение для использования StringBuilder, если бы вам это действительно было нужно, хотя, вероятно, это было бы не так элегантно ..