Building a proof of concept, I've gotten most of it solved, this is just the final step of my proof of concept and I'm hitting a brick wall. I'm building an automatic constructor for a left nav on a ASP.net with Razor Pages based upon the specific definitions contained within a page. The idea is a universal navbar at the top, and a page specific navbar on the left.
List<object> navElements = new List<object> {
new {text = "Test1", location = "test1", subElements = new List<object> {
new {text = "Test1-1", location = "test1-1", subElements = new List<object> {
new {text = "Test1-1-1", location = "test1-1-1"},
new {text = "Test1-1-2", location = "test1-1-2"},
new {text = "Test1-1-3", location = "test1-1-3"}
} },
new {text = "Test1-2", location = "test1-2", subElements = new List<object> {
new {text = "Test1-2-1", location = "test1-2-1"},
new {text = "Test1-2-2", location = "test1-2-2"},
new {text = "Test1-2-3", location = "test1-2-3"}
} },
new {text = "Test1-3", location = "test1-3", subElements = new List<object> {
new {text = "Test1-3-1", location = "test1-3-1"},
new {text = "Test1-3-2", location = "test1-3-2"},
new {text = "Test1-3-3", location = "test1-3-3"}
} }
} }
};
Notice this test definition is attempting to delve three levels in. I've built a recursive function to catch every layer of subElements contained within the list. The problem arises that because subElement doesn't exist on the final layer, it throws a 'object' does not contain a definition for 'subElements' and no accessible extension method 'subElements' accepting a first argument of type 'object' could be found (are you missing a using directive or an assembly reference?)
It can find both universal properties (text and location).
Found this Stackflow question that suggested to use OBJECT.GetType().GetProperty("PROPERTYNAME") != null
, and that seems to be working just fine, however I still am unable to compile when calling that property after this if block.
How am I able to check for, and call, a variably existing property inside of a generic object?
This check needs to catch for two actions:
Here's the general appearance of the functionized builder.
@{
void navLeftBuilder(List<object> elements)
{
foreach (object element in elements)
{
@if (element.subElements) { navLeftBuilder(element.subElement); }
}
}
}
I've even tried changing the object call to
@{
void navLeftBuilder(List<object> elements)
{
object obj;
foreach (int element in elements)
{
obj = elements[element];
@if (obj.subElements) { navLeftBuilder(obj.subElement); }
}
}
}
Try with something like the following
class NavElement {
public string Text { get; set; }
public string Location { get; set; }
public List<NavElement> SubElements { get; set; }
}
private static void Main()
{
List<NavElement> navElements = new List<NavElement> {
new NavElement{Text = "1", Location = "1", SubElements = new List<NavElement> {
new NavElement{Text = "1-1", Location = "1-1", SubElements = new List<NavElement> {
new NavElement{Text = "1-1-1", Location = "1-1-1"},
new NavElement {Text = "1-1-2", Location = "1-1-2"},
new NavElement {Text = "1-1-3", Location = "1-1-3"}
} },
new NavElement {Text = "1-2", Location = "1-2", SubElements = new List<NavElement> {
new NavElement {Text = "1-2-1", Location = "1-2-1"},
new NavElement {Text = "1-2-2", Location = "1-2-2"},
new NavElement {Text = "1-2-3", Location = "1-2-3"}
} },
new NavElement {Text = "1-3", Location = "1-3", SubElements = new List<NavElement> {
new NavElement {Text = "1-3-1", Location = "1-3-1"},
new NavElement {Text = "1-3-2", Location = "1-3-2"},
new NavElement {Text = "1-3-3", Location = "1-3-3"}
} }
} }
};
With this schema, you can access the properties and the children without reflection.
Console.WriteLine(navElements[0].SubElements[2].SubElements[2].Text);
will print
1-3-3
For the record, this is what would work, but what you should NOT do.
void navLeftBuilder(List<dynamic> elements)
{
foreach (dynamic element in elements)
{
Console.WriteLine($"I'm '{element.text}'");
try
{
navLeftBuilder(element.subElements);
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)
{
// property doesn't exist, ignore
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.