Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/286.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 建模(和映射)具有两级多态性的类层次结构?_C#_Oop_Nhibernate_Mapping_Polymorphism - Fatal编程技术网

C# 建模(和映射)具有两级多态性的类层次结构?

C# 建模(和映射)具有两级多态性的类层次结构?,c#,oop,nhibernate,mapping,polymorphism,C#,Oop,Nhibernate,Mapping,Polymorphism,我遇到的情况是,在父/子层次结构中,我有两个层次的多态性,一个在另一个层次内 我认为最好用一个简单的例子来解释这一点: class Group { public IList<Person> People { get; set; } } class SpecialGroup : Group { public IList<SpecialPerson> People { get; set; } }

我遇到的情况是,在父/子层次结构中,我有两个层次的多态性,一个在另一个层次内

我认为最好用一个简单的例子来解释这一点:

    class Group
    {
        public IList<Person> People { get; set; }
    }

    class SpecialGroup : Group
    {
        public IList<SpecialPerson> People { get; set; }
    }

    class Person {}

    class SpecialPerson : Person {}
类组
{
公共IList人员{get;set;}
}
类特殊组:组
{
公共IList人员{get;set;}
}
类人{}
类特殊人物:人物{}
因此,一个组有一个Person对象列表,而一个专用组(SpecialGroup)有一个Person(SpecialPerson)对象的专用列表

这会编译,但我收到一条警告,说我应该在SpecialGroup.People上使用“new”关键字,因为它隐藏了Group.People属性

我理解这意味着什么,但也许我并不完全理解如何在C#中正确地建模这样的东西。关于如何以更好的方式对此进行建模,您有何想法

还有,你知道NHibernate会怎么做吗?我不确定使用“new”关键字是否会删除它,因为Group.People属性已经映射为不同的类型。有没有更好的方法来建模,以与NH兼容的方式


好的,我想到了一种使用泛型建模的方法:

    abstract class AbstractGroup<PersonType>
        where PersonType : Person
    {
        public IList<PersonType> People { get; set; }
    }

    class Group : AbstractGroup<Person>
    {}

    class SpecialGroup : AbstractGroup<SpecialPerson>
    {}

    class Person {}

    class SpecialPerson : Person {}
抽象类抽象组
where PersonType:Person
{
公共IList人员{get;set;}
}
类组:AbstractGroup
{}
类SpecialGroup:AbstractGroup
{}
类人{}
类特殊人物:人物{}
我想这正是我想要的?现在,这个人可以和SpecialPerson共享特征,但只有SpecialPerson可以添加到SpecialGroup。AbstractGroup基类型可以为任何组的共同特征建模

现在的问题是,如果我尝试绘制这张地图,NH会爆炸吗


作为记录,似乎有些人已经成功地将queryover与泛型类一起使用-对于HQL查询(我的用例),这是不受支持的

我想到的另一种方法是简单地隐藏父级对属性的实现,例如在子类中对重写属性使用“new”关键字-下面的线程讨论了为什么这也不起作用:


到目前为止的结论是:运行时检查和异常,如下面@empi所建议的。

如果您想强制执行
SpecialGroup
只包含
SpecialPerson
的规则,那么您可以通过编程来执行,而不必隐藏人员属性。我猜你有一些方法
AddPerson
。如果有人试图添加非
SpecialPerson
的条目,您可以在
SpecialGroup
中重写它并抛出异常。如果您想获得
SpecialPerson
的列表,那么您可以添加方法
IEnumerable GetSpecialPeople()
并将
Person
强制转换为
SpecialPerson
(由于您正在检查键入
AddPerson
方法,因此它将始终是有效的强制转换)。通过这样做,您不必对人的财产进行阴影处理,NHibernate也可以正常工作。

这种情况也称为“平行”或“双重”继承

通常在一个层次结构中有一个与另一个相关的特定类

虽然应该(不是必需的),但最好每个类都有一个“泛型”或“抽象”类,该类必须被重写,但已经有了依赖性的概念

本例非常适用于图形界面控件,但是, 可能适用于其他场景

在这种特殊情况下,通常最好只显示第一级:

............................................................
....+----------------+................+----------------+....
....|  <<Abstract>>  |..<<contains>>..|  <<Abstract>>  |....
....| AbstractGroup  +<>--------------+ AbstractPerson |....
....|                |................|                |....
....+----------------+................+----------------+....
............................................................
............................................................
....+----------------+................+----------------+....
....|  <<Abstract>>  |..<<contains>>..|  <<Abstract>>  |....
....| AbstractGroup  +<>--------------+ AbstractPerson |....
....|                |................|                |....
....+-------+--------+................+--------+-------+....
............|..................................|............
............|..................................|............
............^..................................^............
............|..................................|............
............|..................................|............
....+-------+--------+................+--------+-------+....
....|  <<Concrete>>  |..<<contains>>..|  <<Concrete>>  |....
....|      Group     +<>--------------+     Person     |....
....|                |................|                |....
....+----------------+................+----------------+....
............|..................................|............
............|..................................|............
............^..................................^............
............|..................................|............
............|..................................|............
....+-------+--------+................+--------+-------+....
....|  <<Concrete>>  |..<<contains>>..|  <<Concrete>>  |....
....|   SchoolGroup  +<>--------------+     Student    |....
....|                |................|                |....
....+----------------+................+----------------+....
............................................................
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
....+----------------+................+----------------+....

....|为什么SpecialGroup需要继承Group?这是一个非常简单的示例-但是SpecialGroup与Group有很多共同点,所以它确实需要继承。这个例子只显示了我认为对问题本身至关重要的东西。是的,这会起作用-每个问题都可以用更多的代码来解决。我希望找到一个利用强类型和编译时安全性,而不是运行时检查的解决方案……如果没有NHibernate,您将如何解决它?你是说这个组包含了Person的集合,然后你试图说SpecialGroup没有。你要么在代码中检查它(或者破解它),要么创建一个没有人的抽象组。当然你可以用泛型来尝试一些解决方案,但我从来没有用NHibernate来尝试过。正如我说的,当然你可以用泛型来尝试一些解决方案,但我从来没有用NHibernate来尝试过。底线是这是可能的,但不要这样做。我感谢你的努力!但是,是的,这是持久模型的一部分-子对象不仅仅是包装在对象中的函数,它们是具有附加属性和功能的不同实体。此外,我发现HQL中不支持泛型查询。因此,我担心@empi的建议是唯一一个对我有效的建议。…。@mindplay.dk:我曾经处理过数据库实体和并行层次结构,但从来没有一起处理过。我还有生成实体的工具,这些实体还有其他缺失的特性。我可能最终会制作自己的实体生成器,支持缺少的功能;-)您使用什么工具生成实体?我正在使用一个根本不能正常工作的工具。…。@mindplay.dk:我使用一个在我的一份工作中提供的自定义工具。其他工作也有自己的工具。我也用过codesmith,但它是paidware。我实际上在寻找一个开源的,并且已经开始了我自己的,但是,还没有完成。