首页 > 解决方案 > 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 块之后调用该属性时我仍然无法编译。

我如何能够检查和调用通用对象内的可变现有属性?

此检查需要捕获两个操作:

  1. 分配必要的样式表代码以允许在每一层中放置下拉框。由于 drop box 的存在依赖于子层的存在。
  2. 触发较低层的递归。这将启用无限层的投递箱,因为它已运行。

这是功能化构建器的一般外观。

@{
    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); }
        }
    }
}

标签: c#objectgenericsproperties

解决方案


尝试以下内容

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
        }
    }
}

推荐阅读