Tôi không biết về bạn, nhưng tôi đã viết mã trong các dự án ở công ty khác, và bây giờ tôi muốn để biết làm thế nào tôi đã làm một cái gì đó! Vì vậy, nó thường nhanh hơn để làm một tìm kiếm web cho câu trả lời, và nó mang lại cho tôi ở đây.
Tuy nhiên, lý do của tôi thì khác. Tôi là đơn vị thử nghiệm, và không quan tâm những gì thuần túy phải nói, nhưng như là một phần của một thiết lập cho một bài kiểm tra đơn vị, tôi đang cố gắng để gọi một trạng thái nhất định cho một đối tượng nhất định. Nhưng trạng thái đó nên được kiểm soát nội bộ. Tôi không muốn một số nhà phát triển khác vô tình lộn xộn với nhà nước, mà có thể có hiệu quả đến nay trên hệ thống. Vì vậy, nó phải được đặt riêng! Tuy nhiên, làm thế nào để bạn đơn vị kiểm tra một cái gì đó như thế mà không cần gọi hành vi (hy vọng) sẽ không bao giờ xảy ra? Trong những tình huống như vậy, tôi tin rằng việc sử dụng sự phản chiếu với thử nghiệm đơn vị là hữu ích.
Cách khác là phơi bày những thứ chúng tôi không muốn tiếp xúc, vì vậy chúng tôi có thể kiểm tra chúng! Vâng, tôi đã thấy điều này trong môi trường thực tế, và chỉ nghĩ về nó vẫn khiến tôi lắc đầu.
Vì vậy, tôi hy vọng rằng mã bên dưới có thể hữu ích.
Có hai phương pháp ở đây chỉ để tách mối quan tâm, thực sự và cũng để hỗ trợ dễ đọc. Phản ánh là công cụ quay đầu cho hầu hết các nhà phát triển, những người trong kinh nghiệm của tôi hoặc né tránh nó, hoặc tránh nó như bệnh dịch hạch!
private string _getBackingFieldName(string propertyName)
{
return string.Format("<{0}>k__BackingField", propertyName);
}
private FieldInfo _getBackingField(object obj, string propertyName)
{
return obj.GetType().GetField(_getBackingFieldName(propertyName), BindingFlags.Instance | BindingFlags.NonPublic);
}
Tôi không biết quy tắc mã nào bạn làm việc, nhưng cá nhân tôi thích phương thức trợ giúp riêng tư và bắt đầu bằng chữ thường. Tôi không thấy điều đó đủ rõ ràng khi đọc, vì vậy tôi cũng thích dấu gạch dưới trước đó.
Có thảo luận về các trường sao lưu và đặt tên tự động của chúng. Với mục đích kiểm tra đơn vị, bạn sẽ biết khá nhanh nếu nó đã thay đổi hay không! Nó sẽ không thảm khốc với mã thực sự của bạn, chỉ là các bài kiểm tra. Vì vậy, chúng tôi có thể đưa ra các giả định đơn giản về việc đặt tên cho các tên — như tôi đã nói ở trên. Bạn có thể không đồng ý, và điều đó là tốt.
Trình trợ giúp khó khăn hơn _getBackingField
trả về một trong các loại phản ánh đó, FieldInfo
. Tôi cũng đã đưa ra một giả định ở đây, rằng trường hậu thuẫn mà bạn đang theo sau là từ một đối tượng là một cá thể, trái ngược với việc là tĩnh. Bạn có thể phá vỡ điều đó thành các đối số để được thông qua nếu bạn muốn, nhưng các vùng biển chắc chắn sẽ lầy lội hơn với nhà phát triển trung bình, những người có thể muốn các chức năng nhưng không phải là sự hiểu biết.
Điều tiện dụng về FieldInfo
s là chúng có thể đặt trường trên đối tượng khớp với FieldInfo
. Điều này được giải thích tốt hơn với một ví dụ:
var field = _getBackingField(myObjectToChange, "State");
field.SetValue(myObjectToChange, ObjectState.Active);
Trong trường hợp này, trường có kiểu liệt kê được gọi là ObjectState
. Tên đã được thay đổi để bảo vệ người vô tội! Vì vậy, trong dòng thứ hai, bạn có thể thấy rằng bằng cách truy cập vào các FieldInfo
trả về trước đó, tôi có thể gọi theo phương pháp SetValue
, mà bạn có thể nghĩ rằng nên có liên quan đến đối tượng của bạn, nhưng không! Đây là bản chất của sự phản chiếu - FieldInfo
phân tách một trường từ nơi nó đến, vì vậy bạn phải nói cho nó biết ví dụ nào để làm việc với (myObjectToChange
) và do đó, giá trị bạn muốn nó có, trong trường hợp này là ObjectState.Active
. Vì vậy, để lập một câu chuyện dài, lập trình hướng đối tượng sẽ ngăn cản chúng ta làm những điều khó chịu như truy cập vào các trường tư nhân, và tệ hơn, thay đổi chúng khi nhà phát triển mã không có ý định. Cái nào tốt! Đó là một trong những lý do C# rất có giá trị và được các nhà phát triển ưa thích.
Tuy nhiên, Microsoft đã cho chúng tôi phản ánh, và thông qua nó, chúng tôi sử dụng một vũ khí hùng mạnh. Nó có thể xấu xí, và rất chậm, nhưng đồng thời, nó phơi bày chiều sâu bên trong của các hoạt động bên trong của MSIL (MicroSoft Intermediate Language) —IL cho ngắn — và cho phép chúng ta phá vỡ mọi quy tắc trong cuốn sách, là một ví dụ điển hình.
tò mò !! Tại sao bạn lại muốn điều đó? – Azodious
Lập trình để thực hiện là nguy hiểm. – Eranga
Bạn có thể truy cập nó với sự phản ánh riêng tư, nhưng đó là một ý tưởng tồi. – CodesInChaos