2012-07-17 24 views
21

Tôi muốn viết bài kiểm tra đơn vị cho lớp dưới đây.
Nếu tên không phải là "MyEntity" thì mgr phải để trống.
Kiểm tra đơn vị tiêu cực
Sử dụng Trình quản lý riêng tư của người quản lý Tôi muốn đổi tên thành "Kiểm tra" để mgr phải rỗng. Và sau đó sẽ xác minh giá trị mgr. Để đạt được điều này, tôi muốn gọi một cách rõ ràng các nhà xây dựng tĩnh nhưng khi tôi gọi constructor tĩnh nhờ sủ dụngGọi hàm lập phương tĩnh một cách rõ ràng

Manager_Accessor.name = "Test" 
typeof(Manager).TypeInitializer.Invoke(null, null); 

tên luôn được thiết lập để "MyEntity" làm thế nào để đặt tên cho "Test" và gọi các constructor tĩnh .

public class Manager 
{   
     private static string name= "MyEntity"; 

     private static object mgr; 

     static Manager() 
     { 
      try 
      { 
       mgr = CreateMgr(name); 
      } 
      catch (Exception ex) 
      { 
       mgr=null; 
      } 
     } 
} 
+2

Đặt 'mgr' static có nghĩa là * tất cả * phiên bản 'Manager' chia sẻ * cùng * ' mgr 'giá trị, mà cũng có thể không bao giờ được thay đổi (vì nó chỉ đọc). Đó có thực sự là điều bạn muốn không? –

+3

Vì vậy, bạn cần phải thay đổi một giá trị tĩnh mã hóa riêng tư chịu trách nhiệm thiết lập một giá trị đọc riêng tư tĩnh cho mục đích thử nghiệm? Đây là lý do tại sao hầu hết các lựa chọn thiết kế cho thử nghiệm không thích statics. –

Trả lời

27

Như tôi đã phát hiện ra ngày hôm nay, các nhà xây dựng tĩnh có thể được gọi trực tiếp:

từ another Stackoverflow post

Những câu trả lời khác là tuyệt vời, nhưng nếu bạn cần để buộc một constructor lớp để chạy mà không có tham chiếu đến loại (ví dụ: phản ánh), bạn có thể sử dụng:

Type type = ...; 
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle); 

Tôi phải thêm mã này vào ứng dụng của mình to work around a possible bug in the .net 4.0 CLR.

4

Nếu bạn có một thành viên tĩnh trong lớp của bạn (phải có, nếu không thì hàm tạo tĩnh sẽ không làm quá nhiều) thì không cần gọi rõ ràng hàm tạo tĩnh.

Chỉ cần truy cập vào lớp mà bạn muốn gọi hàm tạo tĩnh của nó. Ví dụ:

public void MainMethod() 
{ 
    // Here you would like to call the static constructor 

    // The first access to the class forces the static constructor to be called. 
    object temp1 = MyStaticClass.AnyField; 

    // or 
    object temp2 = MyClass.AnyStaticField; 
} 
2

Cho bất kỳ ai tìm thấy chuỗi này và tự hỏi ... Tôi vừa làm bài kiểm tra. Nó xuất hiện System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor() sẽ chỉ chạy hàm khởi tạo tĩnh nếu nó có không phải đã được chạy vì một lý do khác.

Ví dụ: nếu mã của bạn không phải là mã dương hay không mã trước đó có thể đã truy cập vào lớp và kích hoạt hàm tạo tĩnh để chạy không, điều đó không quan trọng. Truy cập trước đó sẽ kích hoạt hàm dựng tĩnh để chạy, nhưng sau đó RunClassConstructor() cũng sẽ không chạy nó. RunClassConstructor() chỉ chạy hàm tạo tĩnh nếu nó chưa được chạy.

Truy cập lớp sau RunClassConstructor() cũng không không phải là dẫn đến hàm tạo tĩnh đang chạy lần thứ hai.

Điều này được dựa trên thử nghiệm trong ứng dụng UWP của Win10.

+0

Điều đó làm cho tôi vô cùng buồn như bây giờ bất cứ khi nào tôi muốn đặt lại giá trị của lớp tĩnh của tôi, tôi cần gọi phương thức tĩnh của nó thực hiện chính xác điều tương tự mà hàm tạo làm - đặt giá trị mặc định. –

+0

Chính xác. Bạn không phải "xây dựng" các đối tượng một lần nữa. Chỉ đặt giá trị của chúng. Giả sử bạn đã xây dựng một đối tượng không tĩnh và lưu trữ các tham chiếu đến nó trong một loạt các vị trí khác nhau trong mã của bạn. Bây giờ bạn muốn đặt lại giá trị của đối tượng. Bạn sẽ không tái tạo lại ("mới") đối tượng một lần nữa. Tất cả các tài liệu tham khảo được lưu trữ cũ sẽ vẫn là đối tượng cũ. Thay vào đó bạn sẽ có một phương thức thiết lập lại các giá trị trên đối tượng đã được xây dựng. Sau đó, bạn sẽ nhận ra constructor và các phương thức reset đã làm điều tương tự, vì vậy bạn chỉ cần gọi phương thức reset từ constructor. – kburgoyne

0

Đặt mã mà bạn muốn gọi trong hàm tạo vào một phương thức công khai và gọi nó từ hàm tạo