Edited:
I'm querying some XML into objects recursively. Each object has a list of sub objects, and should refer to it's parent if it has one.
Example XML:
<object attribute1="text" attribute2="text"/>
<object attribute1="text" attribute2="开发者_运维知识库text">
<object attribute1="text" attribute2="text">
<object attribute1="text" attribute2="text">
</object>
Example Linq:
private static List<MyObject> ParseMyObjects(XElement node, MyObject p)
{
List<MyObject> myobjs = (from x in node.Elements("object")
select new MyObject {
attribute1 = x.Attribute("attribute1 ").Value,
attribute2 = x.Attribute("attribute2 ").Value,
subObjects = ParseMyObjects(x, this), // the "this" key word can't refer to the MyObject being created in the query, but is there some other way of doing this?
parent= p
}).ToList();
return myobjs;
}
To accomplish this currently, I am recursively traversing the MyObjects list AFTER it has been queried and setting each parent (the "parent" line above is excluded).
I would simply prefer a more elegant solution of using the newly instantiated object within the Linq query if possible. Any ideas?
Edit: To clarify (as BrokenGlass did in a comment), the this that the code comment is referring to is the instance of MyObject that is being created within the query
this
can't work in a method marked static
ever. There is no instance because the method is static.
I would simply prefer a more elegant solution of using the newly instantiated object within the Linq query if possible. Any ideas?
Just use XObject.Parent
as in
parent = x.Parent
If you want the Parent
member of the created MyObject
instance to point to the instance itself, there are two ways to achieve this without adding code that iterates over the list after the Linq query:
1) Add a constructor that sets it up for you, e.g. the default constructor
public MyObject() {
this.Parent = this;
}
2) Add a fluent-interface style method for setting the parent, and invoke it in the query:
/* in class MyObject */
public MyObject WithSelfAsParent() {
this.Parent = this;
return this;
}
/* updated linq query */
List<MyObject> myobjs = (from x in node.Elements("object")
select new MyObject {
attribute1 = x.Attribute("attribute1 ").Value,
attribute2 = x.Attribute("attribute2 ").Value,
subObjects = ParseMyObjects(x),
}.WithSelfAsParent()).ToList();
Whether these are better than explicitly looping over the list is of course a matter of taste. I would probably just keep it simple and choose the loop, unless the assumption that the parent pointer is equal to this by default is obvious in the context of your MyObject
class, which makes setting it in the default constructor the natural choice.
The solution for me was to harness the set of the subObjects property on MyObject.
class MyObject {
....
private List<MyObject> _subObjects = new List<MyObject>();
public List<MyObject> subObjects
{
get { return _subObjects ; }
set
{
_subObjects = value;
if(_subObjects != null)
{
foreach(MyObject o in _subObjects )
{
o.parent = this;
}
}
}
}
....
}
If anyone does know of a way to reference the newly created/selected object within the Linq syntax, I will mark your answer as the corrrect one.
精彩评论