可以从NHibernate实体的构造函数中调用虚拟属性吗?

时间:2009-01-21 14:04:50

标签: nhibernate

看一下这个示例代码:

public class Comment
{
    private Comment()
    { }

    public Comment(string text, DateTime creationDate, string authorEmail)
    {
        Text = text;
        CreationDate = creationDate;
        AuthorEmail = authorEmail;
    }

    public virtual string Text { get; private set; }
    public virtual DateTime CreationDate { get; set; }
    public virtual string AuthorEmail { get; private set; }
}

我知道从构造函数调用虚拟成员函数被认为是不好的做法,但是在NHibernate中我需要虚拟属性来支持延迟加载。在这种情况下它被认为是好的吗?

6 个答案:

答案 0 :(得分:5)

我很确定这很好,但如果你担心你总是可以在参数较少的构造函数调用之后分配属性。

答案 1 :(得分:2)

扩展Paco的答案:

在大多数情况下,它不会受到伤害。但是如果继承了类,则virtual允许覆盖属性get / set,因此行为不再完全封装和控制,因此理论上它可能会中断。 FxCop对此提出警告,因为这是一个潜在的问题。

FxCop的观点是帮助警告你潜在的问题。如果您知道从类中继承谁/什么,那么在构造函数中使用属性不是错误,但它不是正式的“最佳实践”。

所以,答案是,只要你控制了类的任何继承,它就没问题了。否则,请勿使用它并直接设置字段值。 (这意味着您不能使用C#3.0自动获取/设置属性 - 您必须自己编写包装字段的属性。)

旁注:就我个人而言,我的所有项目都是我们为客户托管的网站。因此,假设这个设置对于项目保持不变,那么必须权衡必须复制各种空值/参数检查。但是,在任何其他我不确定我们将完全控制项目和使用该类的情况下,我不会采用这种捷径。

答案 2 :(得分:1)

此示例中没有问题,但是在继承类并覆盖属性时可能会导致问题。通常,您可以更好地为虚拟属性创建字段。

答案 3 :(得分:1)

恕我直言,最佳做法是使用具有支持字段的属性:

public class Comment
{
    private DateTime _creationDate;
    private string _text;
    private string _authorEmail;
    private Comment() { }
    public Comment(string text, DateTime creationDate, string authorEmail)
    {
        _text = text;
        _creationDate = creationDate;
        _authorEmail = authorEmail;
    }
    public virtual string Text
    {
        get { return _text; }
        private set { _text = value; }
    }
    public virtual string AuthorEmail
    {
        get { return _authorEmail; }
        private set { _authorEmail = value; }
    }
    public virtual DateTime CreationDate
    {
        get { return _creationDate; }
        set { _creationDate = value; }
    }
}

因此,您可以避免儿童课程出现问题,而且您再也看不到任何警告

答案 4 :(得分:0)

我知道如果你在构造函数中调用虚方法,FxCop会抱怨,但是我不知道FxCop说你是否在构造函数中调用虚拟属性...
我认为FxCop也会抱怨,因为属性被转换为IL中的方法。

您还可以将属性创建为“非虚拟”,并在NHIbernate中的“类映射”上指定“lazy = false”。 这不会影响集合的延迟加载行为。

(我一直这样做,因为我不喜欢我的基础设施(NHibernate)要求我将属性设置为虚拟。
我也不知道在NHibernate中使用动态代理的性能优势是否显着。)

答案 5 :(得分:0)

我认为,你不应该在构造函数中调用它。 您可以提供一个方法Initialize(),您可以在构造对象后调用它。

在Initialize()中,您可以调用所需的虚拟方法