2008-09-06 29 views
10

Tôi đã tự hỏi về sự phù hợp của sự phản chiếu trong mã C#. Ví dụ tôi đã viết một hàm lặp qua các thuộc tính của một đối tượng nguồn đã cho và tạo một thể hiện mới của một kiểu được chỉ định, sau đó sao chép các giá trị của các thuộc tính có cùng tên từ một đến cái kia. Tôi tạo ra điều này để sao chép dữ liệu từ một đối tượng LINQ được tạo tự động sang đối tượng khác để tránh việc thừa hưởng từ nhiều bảng trong LINQ. Tuy nhiên, tôi không thể không nghĩ rằng mã như thế này thực sự là 'gian lận', tức là thay vì sử dụng các cấu trúc ngôn ngữ được cung cấp để đạt được một kết thúc nhất định, nó cho phép bạn phá vỡ chúng.Sự biện minh cho sự phản ánh trong C#

Loại mã này có thể chấp nhận ở mức độ nào? Những rủi ro là gì? Cách sử dụng hợp pháp của phương pháp này là gì?

Trả lời

1

Nó có thể chỉ là tôi, nhưng cách tôi nhận được vào điều này là bằng cách tạo ra một bộ tạo mã - sử dụng sự phản chiếu trong thời gian chạy là một chút tốn kém và không được phân loại. Tạo các lớp học sẽ được tạo theo mã mới nhất của bạn và sao chép mọi thứ theo cách được gõ mạnh mẽ có nghĩa là bạn sẽ bắt gặp các lỗi này tại thời gian xây dựng.

Ví dụ, một lớp được tạo ra có thể trông như thế này:

static class AtoBCopier 
{ 
    public static B Copy(A item) 
    { 
     return new B() { Prop1 = item.Prop1, Prop2 = item.Prop2 }; 
    } 
} 

Nếu một trong hai lớp không có các thuộc tính hoặc các loại của họ thay đổi, mã không biên dịch. Thêm vào đó, có một sự cải thiện rất lớn về thời gian.

2

Tôi đồng ý, nó mang lại cho tôi hoạt động nhưng cảm giác giống như một cảm giác hack. Tôi cố gắng tránh sự phản chiếu bất cứ khi nào có thể. Tôi đã bị đốt cháy nhiều lần sau khi mã refactoring đã phản ánh trong nó. Mã biên dịch tốt, kiểm tra thậm chí chạy, nhưng trong trường hợp đặc biệt (mà các bài kiểm tra không bao gồm) chương trình thổi lên thời gian chạy vì tái cấu trúc của tôi trong một trong các đối tượng mà mã phản chiếu được chọc vào.

Ví dụ 1: Phản ánh trong OR Mapper, bạn thay đổi tên hoặc loại thuộc tính trong mô hình đối tượng của bạn: Thổi thời gian chạy.

Ví dụ 2: Bạn đang ở trong một cửa hàng SOA. Dịch vụ web hoàn toàn được tách riêng (hoặc bạn nghĩ vậy). Họ đã thiết lập riêng của họ về các lớp proxy được tạo ra, nhưng trong bản đồ bạn quyết định tiết kiệm thời gian và bạn làm điều này:

ExternalColor c = (ExternalColor)Enum.Parse(typeof(ExternalColor), 
              internalColor.ToString()); 

Dưới sự bao trùm này cũng phản ánh nhưng thực hiện bởi các khung lưới riêng của mình. Điều gì sẽ xảy ra nếu bạn quyết định đổi tên InternalColor.Grey thành InternalColor.Gray? Mọi thứ đều ok, nó xây dựng tốt, và thậm chí chạy tốt .. cho đến ngày một số người dùng ngu ngốc quyết định sử dụng màu xám ... tại thời điểm mà người lập bản đồ sẽ thổi lên.

8

Đôi khi việc sử dụng sự phản chiếu có thể hơi khó khăn, nhưng rất nhiều lúc nó đơn giản là công cụ mã tuyệt vời nhất.

Nhìn vào lưới thuộc tính .Net - bất kỳ ai sử dụng Visual Studio sẽ quen thuộc với nó. Bạn có thể trỏ nó vào bất kỳ đối tượng nào và nó sẽ tạo ra một trình soạn thảo thuộc tính đơn giản. Điều đó sử dụng sự phản chiếu, trên thực tế hầu hết các hộp công cụ của VS.

Xem xét các bài kiểm tra đơn vị - chúng được tải bằng phản ánh (ít nhất là ở NUnit và MSTest).

Phản ánh cho phép hành vi kiểu động từ các ngôn ngữ tĩnh.

Điều duy nhất nó thực sự cần là gõ vịt - trình biên dịch C# đã hỗ trợ điều này: bạn có thể foreach bất kỳ thứ gì trông giống như IEnumerable, cho dù nó có thực hiện giao diện hay không. Bạn có thể sử dụng cú pháp thu thập C# 3 trên bất kỳ lớp nào có phương thức có tên là Add.

Sử dụng phản chiếu ở mọi nơi bạn cần hành vi kiểu động - ví dụ: bạn có một bộ sưu tập các đối tượng và bạn muốn kiểm tra cùng một thuộc tính trên mỗi đối tượng.

Rủi ro tương tự đối với các loại động - ngoại lệ thời gian biên dịch trở thành các trường hợp thời gian chạy. Bạn mã không phải là 'an toàn' và bạn phải phản ứng tương ứng.

Mã phản chiếu .Net rất nhanh, nhưng không nhanh như lời gọi rõ ràng sẽ có.

+0

Nếu tôi được hỏi ý kiến ​​của người ủng hộ và phản đối là gì, đây có phải là câu trả lời phù hợp không? –

1

Gần đây tôi đã sử dụng phản chiếu trong C# để tìm các triển khai của một giao diện cụ thể. Tôi đã viết một thông dịch viên theo kiểu lô đơn giản, tìm kiếm "các hành động" cho mỗi bước tính toán dựa trên tên lớp. Phản ánh không gian tên hiện tại sau đó bật lên việc thực hiện quyền của Inttace IStep của tôi có thể là Execute() ed. Bằng cách này, việc thêm "hành động" mới dễ dàng như việc tạo một lớp dẫn xuất mới - không cần thêm nó vào sổ đăng ký, hoặc thậm chí tệ hơn: quên thêm nó vào sổ đăng ký ...

2

Phản ánh là một công cụ tuyệt vời mà tôi không thể sống thiếu. Nó có thể làm cho lập trình dễ dàng hơn và nhanh hơn.

Ví dụ: tôi sử dụng sự phản chiếu trong lớp ORM của mình để có thể gán thuộc tính với các giá trị cột từ bảng. Nếu nó không được cho sự phản ánh, tôi đã phải tạo một lớp sao chép cho mỗi bảng/ánh xạ lớp.

Đối với ngoại lệ màu bên ngoài ở trên. Vấn đề không phải là Enum.Parse, nhưng bộ mã hóa đã không bắt được ngoại lệ thích hợp. Vì một chuỗi được phân tích cú pháp, trình coder nên luôn luôn giả sử rằng chuỗi có thể chứa một giá trị không chính xác.

Vấn đề tương tự cũng áp dụng cho tất cả các chương trình nâng cao trong .Net. "Với sức mạnh lớn đến trách nhiệm lớn". Sử dụng sự phản chiếu mang đến cho bạn nhiều quyền lực. Nhưng hãy chắc chắn rằng bạn biết cách sử dụng nó đúng cách. Có hàng tá ví dụ trên web.

0

Phản ánh giúp dễ dàng triển khai các kiến ​​trúc plugin nơi plugin DLL được tải tự động khi chạy (không được liên kết rõ ràng tại thời gian biên dịch).

Có thể quét các lớp này để triển khai/mở rộng các giao diện/lớp học có liên quan. Sau đó, sự phản chiếu có thể được sử dụng để khởi tạo các trường hợp này theo yêu cầu.

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