c#查找其他对象的子对象

c#查找其他对象的子对象,c#,oop,C#,Oop,我正在(开始)使用Revit编程。为了简化我的问题,我举了这个例子 我有一个像OOP一样构建的图形。图形中的对象是C#对象。在这幅画里,我有一座房子,房子里有房间,房间里有其他物体等等。所有这些不同的对象都可以嵌套得很深。例如,其中一些对象包含螺钉。为了找到房子里所有的螺丝钉,我必须搜索所有的对象层次结构。但是我怎么知道我已经找到了所有的螺丝钉,这需要很长时间 如果我有发言权,每次我创建一个螺丝,我都会把它放在一个定制的集合中。但我无法控制这个过程。当我得到这幅画时,它可能已经画出来了 所以我的

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

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

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

所以我的问题是:有没有一种方法可以根据螺钉是(a型)螺钉这一事实来创建螺钉集合

如果不是,这是OOP中的一个缺陷还是有一个很好的理由(安全性)


提前感谢。

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)
        {
        }
    }
}
类程序
{
静态void Main(字符串[]参数)
{
房屋h=新房屋();
WriteLine(“这个房子有{0}个螺丝钉”,h.FindAll().Count());
}
公共接口组件
{
IHouseComponent父项{get;}
IEnumerable FindAll(),其中T:IHouseComponent;
IEnumerable子项{get;}
}
公共抽象类HouseComponentBase:IHouseComponent
{
私有列表_children=新列表();
受保护的房屋组件库(iHouseComponentBase)
{
父母=父母;
}
受保护的void AddChild(IHouseComponent组件)
{
_添加(组件);
}
公共IHouseComponent父项{get;private set;}
公共IEnumerable子项{get{return\u Children;}
public IEnumerable FindAll(),其中T:IHouseComponent
{
var list=新列表();
list.AddRange(_children.OfType());//在直接子对象中添加适当的组件
foreach(子节点中的var节点)
list.AddRange(node.FindAll());//然后添加属于子体的所有组件
退货清单;
}
}
公共类房屋:HouseComponentBase
{
酒店()
:base(空)
{
//双室住宅
AddChild(新房间(本));
AddChild(新房间(本));
}
}
公共教室:HouseComponentBase
{
公共房间(家长公寓)
:基(父)
{
//每个房间4面墙-无天花板或地板
AddChild(新墙(本));
AddChild(新墙(本));
AddChild(新墙(本));
AddChild(新墙(本));
}
}
公共类墙:HouseComponentBase
{
公共墙(父房间)
:基(父)
{
对于(int i=0;i<64;i++)
AddChild(新螺钉(此));//每面墙有64个螺钉
}
}
公共级螺钉:HouseComponentBase
{
公共螺钉(IHouseComponent父级)//螺钉可以是任何组件的一部分
:基(父)
{
}
}
}
对于一个简单的房子模型来说,这是可行的,但随着你对模型进行越来越详细的缩放(添加地板、天花板、石膏板、螺柱、家具等),它将无法很好地缩放,因为所有的东西都会一直保存在记忆中。例如,如果您试图对实际房屋的复杂CAD图纸进行建模,并确定材料清单,那么这个简单的实现可能会压倒任何机器。您可能想弄清楚如何存储应用程序状态和检索应用程序状态,这样它就不需要一直在RAM中,但仍然允许查询和检查它,而使用代码则是不明智的。这就是OOP的真正威力


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

感谢您详细的回答。将此信息保存在数据库中是一个很好的建议。从CAD程序设计师的角度来看,我理解他们用于构建图形的结构。它们为更大的物体(如墙壁)提供过滤器。但我想用“螺丝钉”来创建模拟,并且这些数据隐藏在清晰可见的地方。问题是我无法确定我是否有所有的螺丝钉,也无法测试所有的可能性。