C# 在C中调用虚方法的替代方法#

C# 在C中调用虚方法的替代方法#,c#,constructor,virtual,C#,Constructor,Virtual,我将NHibernate用于我的C#项目,因此我有几个模型类 让我们假设以下示例: using System; namespace TestProject.Model { public class Room { public virtual int Id { get; set; } public virtual string UniqueID { get; set; } public virtual int RoomID { ge

我将NHibernate用于我的C#项目,因此我有几个模型类

让我们假设以下示例:

using System;

namespace TestProject.Model
{
    public class Room
    {
        public virtual int Id { get; set; }
        public virtual string UniqueID { get; set; }
        public virtual int RoomID { get; set; }
        public virtual float Area { get; set; }

    }
}
到目前为止,使用NHibernate映射这些对象效果很好。现在我想生成一个新的房间对象,并将其存储在数据库中。为了避免单独设置每个成员,我向模型类添加了一个新的构造函数。 下面是我写的虚拟成员:

public RoomProperty()
{

}


public RoomProperty(int pRoomId, int pArea)
{
        UniqueID = Guid.NewGuid().ToString();
        RoomID = pRoomId;
        Area = pArea;
}
使用FxCop分析代码会告诉我以下几点:

"ConstructorShouldNotCallVirtualMethodsRule"
This rule warns the developer if any virtual methods are called in the constructor of a non-sealed type. The problem is that if a derived class overrides the method then that method will be called before the derived constructor has had a chance to run. This makes the code quite fragile. 
也描述了为什么这是错误的,我也理解它。但我不是舒尔如何解决这个问题

当我删除所有构造函数并添加以下方法时

public void SetRoomPropertyData(int pRoomId, int pArea)
        {
            UniqueID = Guid.NewGuid().ToString();
            RoomID = pRoomId;
            Area = pArea;

        }
。。。。要在调用标准构造函数后设置数据,我无法启动应用程序,因为NHibernate初始化失败。它说:

NHibernate.InvalidProxyTypeException: The following types may not be used as proxies:
VITRIcadHelper.Model.RoomProperty: method SetRoomPropertyData should be 'public/protected virtual' or 'protected internal virtual'
但是,将此方法设置为virtual与在构造函数中设置虚拟成员时的错误相同。
如何避免这些错误(违规)?

问题在于虚拟集。将值传递给基类构造函数中的虚拟属性将使用重写集而不是基集。若重写集依赖于派生类中的数据,那个么您就有麻烦了,因为派生类的构造函数还并没有完成

若您完全确定,任何子类都不会在重写集中使用其状态的任何数据,那个么您可以在基类构造函数中初始化虚拟属性。考虑对文档添加适当的警告。

如果可能,尝试为每个属性创建支持字段,并在基类构造函数中使用它们


还可以将属性初始化推迟到派生类。要实现这一点,请在基类中创建一个初始化方法,您可以在派生类的构造函数中调用该方法。

我希望以下方法之一能够起作用:

  • 将属性设置为非虚拟(首选,只要NHibernate支持)
  • 从自动实现的属性更改为具有显式支持字段的属性,并在构造函数中设置字段,而不是设置属性
  • 创建一个静态
    Create
    方法,该方法首先构造对象,然后在返回构造的对象之前设置属性值
  • 编辑:我看到的评论选项3不清楚

    public class Room
    {
        public virtual int Id { get; set; }
        public virtual string UniqueID { get; set; }
        public virtual int RoomID { get; set; }
        public virtual float Area { get; set; }
    
        public static Room Create(int roomId, int area)
        {
            Room room = new Room();
            room.UniqueID = Guid.NewGuid().ToString();
            room.RoomID = roomId;
            room.Area = area;
            return room;
        }
    }
    

    嗯,好主意是使基类-抽象及其构造函数-受保护
    接下来,继承的类有它们的构造函数private,对于外部世界,还有统一的静态方法,比如“Instance”,它首先初始化构造函数,然后-按正确的顺序调用整个类方法集,最后-返回类的实例。

    为什么不在构造时为字段而不是属性设置值?@voroninp您无法使用NHibernate轻松访问字段,因为我的模型实际上有大约10个成员,我创建了新的房间对象qiet iften。我不想单独设置每个属性。@Metalhead89代码片段(甚至T4)不会有帮助吗?我不得不承认我不是舒尔,因为isNHibernate不支持非虚拟属性。我也不能将创建方法设置为静态,因为这样属性也必须是静态的,这不是我想要的(如果这样做可行,我也不是舒尔)。我编辑了我的帖子以澄清选项3。
    Create
    方法是静态的,但属性不是静态的。如果使构造函数受保护,则选项3更有意义,因此构造
    Room
    实例的唯一方法是使用静态方法。