2009-01-21 28 views
19

hãy nhìn vào mã ví dụ này:Có thể gọi các thuộc tính ảo từ hàm tạo của thực thể NHibernate không?

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

tôi biết nó được coi là xấu thực hành để gọi hàm thành viên ảo từ các nhà xây dựng, tuy nhiên trong NHibernate tôi cần các thuộc tính là ảo để hỗ trợ tải lười biếng. Được coi là OK trong trường hợp này?

+1

Tôi nghĩ rằng câu hỏi của bạn xứng đáng hơn sự chú ý và tôi muốn thêm tham chiếu này: http://stackoverflow.com/search?q=nhibernate+virtual+constructor Tôi nghĩ rằng việc thêm một phương thức Initialize() hoặc một tham số ít hàm tạo đang thay đổi thiết kế của bạn để thích ứng với khuôn khổ - đó là một thực hành tồi trong quan điểm của tôi; có lẽ bạn muốn đối tượng của bạn là hợp lệ mọi lúc (tôi nghĩ bạn nên) ... Initialize() phương thức/tham số constructor ít cho phép xây dựng các đối tượng mà không cần chúng. – W3Max

Trả lời

5

Tôi khá chắc chắn điều này là tốt, nhưng nếu bạn lo lắng bạn luôn có thể chỉ định các thuộc tính sau khi một tham số gọi hàm dựng ít hơn.

0

Tôi biết rằng FxCop than phiền nếu bạn gọi một phương pháp ảo trong hàm tạo của bạn, nhưng tôi không biết FxCop nói liệu bạn đang gọi một thuộc tính ảo trong hàm tạo của bạn ...
Tôi nghĩ rằng FxCop sẽ cũng phàn nàn vì tài sản được dịch sang phương pháp IL.

Bạn cũng có thể tạo thuộc tính của mình là 'không ảo' và chỉ định 'lazy = false' trên 'ánh xạ lớp' của bạn trong NHIbernate. Điều này sẽ không ảnh hưởng đến hành vi lười biếng của bộ sưu tập.

(Tôi làm điều đó tất cả thời gian, vì tôi không thích rằng cơ sở hạ tầng của tôi (NHibernate) đòi hỏi tôi phải có các thuộc tính ảo. có ý nghĩa).

0

Tôi nghĩ, bạn không nên gọi nó trong hàm tạo. Bạn có thể cung cấp phương thức Initialize() mà bạn có thể gọi sau khi xây dựng đối tượng.

Trong Initialize(), bạn có thể gọi các phương pháp ảo cần

1

Đó là OK trong mẫu này, nhưng nó có thể gây ra vấn đề khi bạn kế thừa lớp và ghi đè các thuộc tính. Nói chung, bạn có thể tạo các trường cho các thuộc tính ảo tốt hơn.

2

Để mở rộng câu trả lời của Paco:

Trong hầu hết các trường hợp, nó không bị tổn thương. Nhưng nếu lớp được thừa hưởng, ảo cho phép các thuộc tính get/set được overriden, do đó, hành vi không còn được đóng gói và kiểm soát đầy đủ, vì vậy nó có thể phá vỡ, theo lý thuyết. FxCop cảnh báo về điều này vì đó là một vấn đề tiềm ẩn.

Điểm của FxCop là giúp cảnh báo bạn về các vấn đề tiềm năng. Nó không phải là sai để sử dụng các thuộc tính trong một hàm tạo nếu bạn biết bạn/ai sẽ kế thừa từ lớp, nhưng nó không phải là 'thực hành tốt nhất' chính thức.

Vì vậy, câu trả lời là miễn là bạn kiểm soát bất kỳ sự thừa kế nào của lớp học. Nếu không, không sử dụng nó và đặt giá trị trường trực tiếp. (Điều đó có nghĩa là bạn không thể sử dụng các thuộc tính get/set tự động C# 3.0 - bạn sẽ phải tự viết các trường thuộc tính.)

Lưu ý: Cá nhân, tất cả các dự án của tôi là các trang web mà chúng tôi lưu trữ cho khách hàng . Vì vậy, giả sử thiết lập này vẫn như nhau cho một dự án, hơn là nó có giá trị thương mại-off của việc phải lặp lại kiểm tra null/đối số khác nhau. Nhưng, trong bất kỳ trường hợp nào khác mà tôi không chắc chắn rằng chúng tôi sẽ duy trì sự kiểm soát hoàn toàn của dự án và sử dụng lớp học, tôi sẽ không dùng lối tắt này.

0

IMHO the-thực hành tốt nhất là sử dụng các thuộc tính với các lĩnh vực ủng hộ:

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

Vì vậy, bạn có thể tránh được vấn đề trên lớp trẻ và bạn không nhìn thấy bất kỳ cảnh báo nữa

Các vấn đề liên quan