C# 查找作为其他对象的子对象

本文关键字:对象 其他 查找 | 更新日期: 2023-09-27 18:36:04

我正在Revit中(开始)编程。为了简化我的问题,我有这个例子。

我有一张像 OOP 一样构建的图纸。图形中的对象是 C# 对象。在这幅画中,我有一个有房间的房子,房间里有其他物体等等。所有这些不同的对象都可以嵌套得很深。例如,其中一些物体包含螺钉。要找到房子里的所有螺丝,我必须搜索所有的对象层次结构。但是我怎么知道我已经找到了所有的螺丝,这需要很长时间。

如果我对它有发言权,每次我创建一个螺丝钉时,我都会把它放在一个定制的集合中。但我无法控制这个过程。当我拿到图纸时,它已经可以画了。

所以我的问题是:有没有办法根据它们是(一种类型)螺钉的事实来创建螺钉集合?

如果不是,这是 OOP 中的缺陷还是有充分的理由(安全性)?

提前谢谢。

C# 查找作为其他对象的子对象

这不是OOP的问题,但更有可能是实现的问题,它必须满足对房屋进行详细建模并列出其所有组成部分的要求。让我们看一个相当幼稚的实现,其中房子的每个部分都有一个父部分,并且有一个子项集合,以及一种递归子项查找特定类型部分的方法:

class Program
{
    static void Main(string[] args)
    {
        House h = new House();
        Console.WriteLine("This house has {0} screws", h.FindAll<Screw>().Count());
    }
    public interface IHouseComponent
    {
        IHouseComponent Parent { get; }
        IEnumerable<T> FindAll<T>() where T : IHouseComponent;
        IEnumerable<IHouseComponent> Children { get; }
    }
    public abstract class HouseComponentBase : IHouseComponent
    {
        private List<IHouseComponent> _children = new List<IHouseComponent>();
        protected HouseComponentBase(IHouseComponent parent)
        {
            Parent = parent;
        }
        protected void AddChild(IHouseComponent component)
        {
            _children.Add(component);
        }
        public IHouseComponent Parent { get; private set; }
        public IEnumerable<IHouseComponent> Children { get { return _children; } }
        public IEnumerable<T> FindAll<T>() where T : IHouseComponent
        {
            var list = new List<T>();
            list.AddRange(_children.OfType<T>()); // add appropriate components in direct children
            foreach (var node in _children)
                list.AddRange(node.FindAll<T>()); // then add all components that are part of descendants               
            return list;
        }
    }
    public class House : HouseComponentBase
    {
        public House()
            : base(null)
        {
            // two room house
            AddChild(new Room(this));
            AddChild(new Room(this));
        }
    }
    public class Room : HouseComponentBase
    {
        public Room(House parent)
            : base(parent)
        {
            // 4 walls per room - no ceiling or floor
            AddChild(new Wall(this));
            AddChild(new Wall(this));
            AddChild(new Wall(this));
            AddChild(new Wall(this));
        }
    }
    public class Wall : HouseComponentBase
    {
        public Wall(Room parent)
            : base(parent)
        {
            for (int i = 0; i < 64; i++)
                AddChild(new Screw(this));// each wall has 64 screws
        }
    }
    public class Screw : HouseComponentBase
    {
        public Screw(IHouseComponent parent) // a screw can be part of any component
            : base(parent)
        {
        }
    }
}

对于一个简单的房屋模型,这将起作用,但随着您的比例建模到越来越多的细节(添加地板、天花板、石板、螺柱、家具等),它不会很好地缩放,因为所有内容始终保存在内存中。例如,如果您尝试对实际房屋的复杂CAD建模并确定物料清单,那么这种简单的实现可能会使任何机器不堪重负。您需要弄清楚如何存储应用程序状态并检索应用程序状态,使其不需要始终位于 RAM 中,但仍允许查询和检查它,而使用代码并不明智。这才是OOP的真正力量。

因此,如果您将内存集合和FindAll方法实现替换为查询 Sql 数据库或 CAD 文件的方法,例如,基本类设计(OOP 部分)仍然可以在很大程度上保持不变。OOP 是关于如何构建类型以最好地对问题域进行建模并组织实现。我可以向你保证,像AutoCAD这样的系统,实际上可以将房屋的设计变成物料清单,在很大程度上依赖于OOP。