2009-01-21 70 views
19

看看这个例子代码:可以从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的,我需要的属性是虚拟的,以支持延迟加载。在这种情况下它被认为是可以的吗?

+1

我觉得你的问题应该得到更多的注意,我想添加此参考:http://stackoverflow.com/tw/sea​​rch?q=nhibernate+virtual+constructor 我认为,添加一个Initialize()方法或参数较少的构造函数正在改变你的设计,以适应框架 - 在我看来这是一个不好的做法;也许你希望你的对象在任何时候都是有效的(我认为你应该)... Initialize()方法/参数少的构造函数允许构造没有它们需要的对象。 – W3Max 2009-08-30 19:48:25

回答

5

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

0

我知道如果你在构造函数中调用一个虚拟方法,但我不知道FxCop说你是否在构造函数中调用一个虚拟属性...
我认为FxCop会因为财产被翻译成IL中的方法,所以也抱怨。

您还可以创建属性为'非虚拟',并在NHIbernate的'类映射'中指定'lazy = false'。 这不会影响集合的延迟加载行为。我一直这样做,因为我不喜欢我的基础设施(NHibernate)要求我具有虚拟属性
我也不知道在NHibernate中具有动态代理的性能好处是不是重大)。

0

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

在初始化(),您可以调用所需的虚拟方法

1

这是该样品中确定,但是当你继承类和替换的属性,可能会出现问题。通常,您可以更好地为虚拟属性创建字段。

2

要扩大Paco的答案:

在大多数情况下,它不会伤害。但是,如果这个类是继承的,虚拟允许属性get/set被重写,所以行为不再被完全封装和控制,因此理论上它可能会破坏。 FxCop对此提出警告,因为这是一个潜在的问题。

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

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

备注:就我个人而言,我所有的项目都是我们为客户托管的网站。因此,假设这个设置对于一个项目来说保持不变,那么就不得不重复不同的空/参数检查。但是,在其他任何情况下,我不确定我们会保持对项目的完全控制和课程的使用,我不会采取这种捷径。

0

恕我直言,最好的做法是使用性能与支持字段:

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; } 
    } 
} 

所以,你就可以避免子类的问题,你看不到任何警告了