c# - C# 检查和调用可能存在或不存在的对象属性
问题描述
建立一个概念证明,我已经解决了大部分问题,这只是我的概念证明的最后一步,我正在碰壁。我正在使用 Razor Pages 根据页面中包含的特定定义在 ASP.net 上为左侧导航构建一个自动构造函数。这个想法是顶部的通用导航栏,左侧的页面特定导航栏。
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"}
} }
} }
};
请注意,此测试定义试图深入研究三个级别。我构建了一个递归函数来捕获列表中包含的每一层子元素。问题出现了,因为 subElement 在最后一层不存在,它会抛出一个
'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?)
它可以找到通用属性(文本和位置)。
找到了建议使用的这个 Stackflow 问题OBJECT.GetType().GetProperty("PROPERTYNAME") != null
,这似乎工作得很好,但是在这个 if 块之后调用该属性时我仍然无法编译。
我如何能够检查和调用通用对象内的可变现有属性?
此检查需要捕获两个操作:
- 分配必要的样式表代码以允许在每一层中放置下拉框。由于 drop box 的存在依赖于子层的存在。
- 触发较低层的递归。这将启用无限层的投递箱,因为它已运行。
这是功能化构建器的一般外观。
@{
void navLeftBuilder(List<object> elements)
{
foreach (object element in elements)
{
@if (element.subElements) { navLeftBuilder(element.subElement); }
}
}
}
我什至尝试将对象调用更改为
@{
void navLeftBuilder(List<object> elements)
{
object obj;
foreach (int element in elements)
{
obj = elements[element];
@if (obj.subElements) { navLeftBuilder(obj.subElement); }
}
}
}
解决方案
尝试以下内容
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"}
} }
} }
};
使用此模式,您无需反射即可访问属性和子项。
Console.WriteLine(navElements[0].SubElements[2].SubElements[2].Text);
将打印
1-3-3
编辑
作为记录,这是可行的,但你不应该这样做。
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
}
}
}
推荐阅读
- python - 计算列表列表中字符串的出现次数
- java - 我可以按键设置@Cacheable 的 TTL 吗?
- excel - 根据另一列的值从相邻列中获取立即值
- javascript - Cheerio 没有正确解析 HTML
- java - 从 Spring 表单中获取 Post 请求中的 null Set 值
- android - firebase Onclick监听器的嵌套不起作用
- wordpress - 在订单上添加自定义字段作为项目元数据
- sql - 如何在 Hive 中分解数组并创建视图?
- html - 对齐文本并将其环绕在图像旁边
- angular - 如何以角度 2 呈现从 WebAPI 获取的图像