Met*_*d89 5 c# virtual constructor
我使用NHibernate作为我的C#pojects,因此我有几个模型类.
让我们假设以下示例:
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; }
}
}
Run Code Online (Sandbox Code Playgroud)
使用NHibernate映射这些对象到目前为止工作正常.现在我想生成一个新的Room对象,我想将它存储在数据库中.为了避免单独设置每个成员,我向模型类添加了一个新的构造函数.在我写的虚拟成员下面:
public RoomProperty()
{
}
public RoomProperty(int pRoomId, int pArea)
{
UniqueID = Guid.NewGuid().ToString();
RoomID = pRoomId;
Area = pArea;
}
Run Code Online (Sandbox Code Playgroud)
使用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.
Run Code Online (Sandbox Code Playgroud)
这个页面还描述了为什么这是错误的,我也理解它.但我不知道如何解决问题.
当我擦除所有构造函数并添加以下方法时...
public void SetRoomPropertyData(int pRoomId, int pArea)
{
UniqueID = Guid.NewGuid().ToString();
RoomID = pRoomId;
Area = pArea;
}
Run Code Online (Sandbox Code Playgroud)
....在我调用标准构造函数后设置数据我无法启动我的应用程序因为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'
Run Code Online (Sandbox Code Playgroud)
但是将此方法设置为virtual将与我在构造函数中设置虚拟成员时的错误相同.我怎样才能避免这些错误(违规)?
问题在于虚拟集。将值传递给基类构造函数中的虚拟属性将使用覆盖集而不是基集。如果覆盖集依赖于派生类中的数据,那么你就有麻烦了,因为派生类的构造函数还没有完成。
如果您绝对确定,任何子类都不会在覆盖集中使用其状态的任何数据,那么您可以在基类构造函数中初始化虚拟属性。考虑在文档中添加适当的警告。
如果可能,尝试为每个属性创建支持字段并在基类构造函数中使用它们。
您还可以将属性初始化推迟到派生类。为此,请在派生类的构造函数中调用的基类中创建一个初始化方法。