11

Gần đây tôi đã nhận thấy một số hành vi với Visual Studio Designer (C#) mà tôi không hiểu và đã tự hỏi nếu ai đó có thể làm rõ ...Tại sao Visual Studio IDE đôi khi khởi tạo đối tượng "this.components" và lần khác không?

Một số Windows Forms của tôi, dòng đầu tiên của nhà thiết kế tạo ra mã đọc;

this.components = new System.ComponentModel.Container(); 

Khi điều này là trường hợp, các phương pháp xử lý, trong đó cùng một tập tin thiết kế, các dispose phương thức đặt hai cuộc gọi "Vứt bỏ" trong trường hợp "nếu" điều kiện như sau;

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
      base.Dispose(disposing); 
     } 
    } 

tức là Không có gì được gọi trừ khi xử lý đúng, VÀ các thành phần không phải là rỗng.

Trên một số biểu mẫu khác, dòng đầu tiên trong mã do nhà thiết kế tạo bị thiếu. Trong những trường hợp này, lệnh gọi cơ bản.Dispose nằm ngoài điều kiện "if" như vậy ...

protected override void Dispose(bool disposing) 
    { 
     if (disposing && (components != null)) 
     { 
      components.Dispose(); 
     } 
     base.Dispose(disposing); 
    } 

Tôi đã nhận thấy điều này trong khi theo dõi lỗi có biểu mẫu không đóng, trong đó this.components rỗng, cuộc gọi base.Dispose là bên trong tình trạng đó (tôi nghi ngờ mã thiết kế đã bị giả mạo nhưng đó là một câu chuyện khác.

gì kiểm soát hành vi này?

(một số hình thức trước đó trong dự án đã được tạo ra trong VS 2005 và bây giờ chúng ta sử dụng VS 2008 - đầu mối?)

Trả lời

4

Đây là hành vi có thể lặp lại. Khi bạn tạo một biểu mẫu mới, nó bắt đầu với một bộ khung bao gồm lời gọi hàm tạo của this.components. Khi bạn thêm một thành phần (nói một Timer) và loại bỏ nó một lần nữa, nhà thiết kế tạo lại mã, bây giờ mà không cần gọi hàm tạo. Đó không phải là lỗi.

Fwiw, mã bộ xương được tạo ra bởi Common7\IDE\ItemTemplates\CSharp\Windows Forms\1033\Form.zip\form.designer.cs

Thấy base.Dispose() gọi bên trong if() tuyên bố là một lỗi. Đó có thể là tự gây ra. Hoặc nó có thể là phiên bản beta của mã bộ xương. VS2005 có đúng không. Hãy kiểm tra thư mục ItemsTemplatesCache.

+0

Cảm ơn nobugz. Tôi đã có một cơ hội để thử kịch bản này trong VS2005 bây giờ quá. Tốt rồi. Tôi chỉ có thể giả định, như bạn nói, đây là "tự gây ra". –

+0

"hiện không có lời gọi hàm tạo". Vì vậy, những gì các điểm trong '(thành phần! = Null)' kiểm tra nếu không có 'thành phần' khởi tạo bất cứ nơi nào nào? Ai, khi nào và ở đâu khởi tạo 'thành phần'? BTW, đến đây từ VS2010, .NET4.0 – Fulproof

+0

Bạn dường như có một câu hỏi mới. Bạn có thể yêu cầu bằng cách nhấp vào nút Hỏi câu hỏi. –

1

Trục trặc thú vị! Nó thực sự âm thanh như một lỗi trong một phiên bản của nhà thiết kế/templating. Tất nhiên, nếu bạn nghĩ rằng mã thiết kế đã bị giả mạo, tất cả các cược là khá-hơn off anyway ...

Tuy nhiên, trong VS2008, nó tạo ra các phiên bản undoubtably đúng:

if (disposing && (components != null)) 
{ 
    components.Dispose(); 
} 
base.Dispose(disposing); 

Vì vậy, các cơ sở Dispose(...) được gọi. Tôi đã không có VS2005 tiện dụng để kiểm tra nó, không may. Tuy nhiên - nó không khởi tạo các thành phần cho đến khi nó phải - tờ khai là:

private System.ComponentModel.IContainer components = null; 

Và sau đó nếu nó là cần thiết, nó được phổ biến trong InitializeComponent:

private void InitializeComponent() 
{ 
    this.components = new System.ComponentModel.Container(); 
    //... 
} 

Tôi đoán với cấu trúc này nó chỉ phải duy trì InitializeComponent (và không phải chính các trường).

+0

Không có tôi hoặc là Marc. Tôi sẽ phải cố gắng ở nhà tối nay. Cảm ơn. –

+0

"nếu bạn nghĩ rằng mã thiết kế đã bị giả mạo" - đó là tôi bởi vì tôi không hiểu làm thế nào để bình tĩnh nó! – Fulproof

0

Tôi đã thấy điều này xảy ra và đôi khi tôi đã nhận được cảnh báo về từ phương thức Vứt bỏ về các thành phần hoặc không bao giờ được gán giá trị hoặc không được xác định.

Tôi nghĩ rằng đó là một sự kết hợp của hai yếu tố:

  1. sinh mã Hơi khác nhau giữa các phiên bản của Visual Studio
  2. Các phương thức Dispose chỉ tạo ra nếu không có một đã có trong hồ sơ, trong khi InitializeComponent (và các khai báo liên quan) được tạo mỗi lần

Điều này dẫn đến phần InitializeComponent/khai báo không đúng với phương pháp Vứt bỏ.

+0

"giữa các phiên bản của Visual Studio" - đến đây từ việc tạo ứng dụng Windows Forms mới trong VS2010, .NET4.0 mà không sử dụng bất kỳ phiên bản nào khác (mặc dù giao diện người dùng có VS2008 được cài đặt trên PC) – Fulproof

3

6 năm sau và sự cố này vẫn xảy ra. Tôi đã quản lý để theo dõi ít ​​nhất một nguyên nhân cho nó xảy ra.

Khi thử nghiệm nếu thành phần của bạn có một hàm tạo có IContainer, System.ComponentModel.Design.Serialization.ComponentCodeDomSerializer lưu trữ một tham chiếu đến Kiểu IContainer cho dự án của bạn. Nếu sau đó bạn lưu một đối tượng cho một dự án khác trong cùng một giải pháp, hoặc có lẽ khi bạn đã thực hiện một số loại thay đổi khác trong dự án của mình, ComponentCodeDomSerializer không còn có thể tìm thấy hàm tạo như Loại IContainer không còn bằng Loại lưu trữ.

Nếu điều này xảy ra rất nhiều cho dự án của bạn, có một giải pháp rất xấu. Thêm lớp này VB hoặc C#VisualStudioWorkaroundSerializer vào giải pháp của bạn. Sau đó, thêm thuộc tính DesignerSerializer(GetType(VisualStudioWorkaroundSerializer), GetType(CodeDomSerializer)) vào thành phần của bạn. Bất cứ khi nào thành phần của bạn được lưu, bộ nối tiếp tùy chỉnh này sẽ phát hiện sự cố, khắc phục sự cố và buộc bạn phải lưu lại bất cứ khi nào sự cố này sắp xảy ra.

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