2009-01-09 17 views

Trả lời

25

Nơi duy nhất tôi đã sử dụng công cụ Phản chiếu trong C# là trong các mẫu nhà máy, nơi tôi đang tạo đối tượng (trong trường hợp của tôi, người nghe mạng) dựa trên thông tin tệp cấu hình. Tập tin cấu hình cung cấp vị trí của các hội đồng, tên của các loại trong chúng, và bất kỳ đối số bổ sung cần thiết. Nhà máy đã chọn công cụ này và tạo ra người nghe dựa trên đó.

+0

Thực hiện tương tự với bảng cơ sở dữ liệu - kích hoạt các tính năng mới/hủy kích hoạt các tính năng lỗi thời bằng cách chỉnh sửa bản ghi cơ sở dữ liệu ... +1 –

+1

Tương tự tại đây. Về cơ bản sử dụng Type.GetType theo sau là Activator.CreateInstance –

3

Tôi sẽ không loại bỏ bất kỳ mẫu nào, nhưng tôi khuyên bạn nên tránh phản chiếu cho đến khi bạn thực sự cần nó. Nó đặc biệt hữu ích cho các tình huống interop và extensibility nơi bạn không thể kiểm soát trước thời hạn kiểu của một đối tượng.

11

Tôi không biết nếu đó là một mẫu nhưng tôi sử dụng sự phản chiếu để tạo SQL từ định nghĩa lớp của DAO.

+1

Tại sao cậu lại tái NHibernate? Chỉ cần sử dụng thỏa thuận thực sự. – yfeldblum

+8

Một trong những lý do là vì DAL của tôi có trước NHibernate. Tôi đã xem xét việc chuyển đổi nhưng không muốn xử lý sự cố cấu hình xml. Để tôi sử dụng những gì tôi có là cách sạch hơn. Nhưng cảm ơn bạn đã đề xuất. –

8

Không có quy tắc cứng và nhanh. Về cơ bản, bạn không sử dụng sự phản chiếu mà không có lý do chính đáng. Sử dụng sự phản chiếu khi bạn không thể làm những gì bạn muốn mà không có nó, hoặc khi mã của bạn sẽ lâu hơn hoặc khó hiểu hơn mà không có sự phản chiếu.

1

Tôi đã dành 2 năm phát triển mà không hiểu mục đích phản ánh. Nó có sử dụng rất thích hợp, nhưng cực kỳ mạnh mẽ khi nó là công cụ thích hợp cho công việc.

Tôi nghĩ rằng những gì tôi đang cố gắng nói là chỉ sử dụng nó khi bạn chắc chắn đó là cách duy nhất để đạt được những gì bạn muốn.

32

Trong một sản phẩm tôi đang làm việc trên chúng tôi sử dụng nó rất nhiều, nhưng Phản ánh là một con thú chậm, phức tạp. Đừng đi tìm những nơi để sử dụng nó chỉ vì nó có vẻ thú vị hoặc thú vị. Bạn sẽ sử dụng nó khi bạn gặp một vấn đề không thể giải quyết theo bất kỳ cách nào khác (tự động nạp các assembly cho các trình cắm thêm hoặc khung công tác, kiểm tra lắp ráp, các nhà máy không biết xây dựng, vv). Nó chắc chắn đáng xem xét hướng dẫn phản chiếu để xem nó hoạt động như thế nào, nhưng không rơi vào cái bẫy "có một cái búa và mọi thứ trông giống như một cái đinh." Nó có trường hợp sử dụng rất chuyên dụng.

+7

+1! Phản ánh là phức tạp, chậm và phá vỡ kiểm tra thời gian biên dịch. Việc lạm dụng nó sẽ làm cho dự án của bạn khó duy trì. –

+8

Lol. Tôi đến đây với một cái búa và mọi thứ trông như một cái đinh. Câu chuyện có thật. –

+0

Câu trả lời tuyệt vời tôi phải nói .... và "có một cái búa và mọi thứ trông giống như một cái đinh" làm tôi cười ... Cảm ơn. –

1

Tôi sử dụng nó trong một trường hợp tương tự như được đề cập bởi Harper Shelby, trong đó tệp cấu hình chỉ định khi chạy có đối tượng để khởi tạo. Trong trường hợp cụ thể của tôi không có gì phức tạp như một nhà máy - chỉ là một tập hợp các lớp thực hiện một giao diện chung, và một hàm đơn giản đọc tệp cấu hình và tạo đối tượng thích hợp, trả về giao diện.

0

Tôi thường xuyên sử dụng nó khi tôi cần phải phá vỡ đóng gói của người khác (thường là khuôn khổ). Đó là, tôi cần phải thay đổi một số lĩnh vực tư nhân, hoặc gọi một phương pháp tư nhân, hoặc tạo ra một thể hiện của một số lớp nội bộ trong một thư viện tôi không có quyền lực để thay đổi. Một ví dụ điển hình là mã trong số my answer đến this question. Trong trường hợp này, hành vi của phương pháp khung ServiceBase.Run là không thể chấp nhận được, vì vậy tôi đã sử dụng sự phản chiếu để làm điều tương tự nó thực hiện theo cách có thể chấp nhận được hơn.

Phản ánh có nhiều cách sử dụng khác, mặc dù, bao gồm duck typing, làm việc với attributeslate binding.

+2

Nếu bạn đang phá vỡ đóng gói của người khác, rất có thể bạn đang làm sai. – abelenky

+0

Ngược lại. Tôi thường làm đúng vì họ đã làm sai. –

+0

nhưng nó vẫn bị hỏng, không có vấn đề mà cách bạn nhìn vào nó :) – gbjbaanb

2

Tôi sử dụng phản ánh số tiền hợp lý trong các bài kiểm tra đơn vị của mình, đặc biệt là khi những thứ tôi đang kiểm tra là các loại ẩn danh. Tôi cũng đã sử dụng nó như một cách để dễ dàng sao chép/sao chép các đối tượng mô hình. Thay vì viết mã để làm điều này cho mọi đối tượng mô hình, tôi có thể dễ dàng tạo một đối tượng của một kiểu cụ thể bằng cách sử dụng sự phản chiếu, thẩm vấn các thuộc tính công khai của đối tượng đến và gọi các settors trên các đối tượng nhân bản tương ứng.Tôi cũng sử dụng nó với các lớp được thiết kế riêng được tạo ra để thực hiện các chữ ký phương thức giống nhau, nhưng không có một giao diện liên quan. Trong những trường hợp đó, tôi có thể thẩm vấn đối tượng để xem nó có phương thức cần thiết không và gọi nó nếu nó có. Các thực thể LINQ2SQL giống như vậy trong phương thức trình bao ngữ cảnh dữ liệu giả của tôi Phương thức OnSubmit tôi sử dụng sự phản chiếu để có được phương thức OnValidate và gọi nó để kiểm thử đơn vị.

3

Tôi sử dụng nó trong bộ nối tiếp nhị phân (protobuf-net). Tôi chỉ sử dụng sự phản chiếu để xây dựng mô hình - khi nó được sử dụng (tức là trong quá trình [serialization]) nó đang sử dụng các đại biểu vv cho hiệu suất tối đa.

Tôi cũng đã sử dụng nó (cùng với ComponentModel và Reflection.Emit) trong HyperDescriptor, để xây dựng quyền truy cập thuộc tính tăng tốc (~ 100x tốc độ phản xạ thông thường).

Và do cần thiết, bạn cần sử dụng phản chiếu nếu bạn là building your own Expressions.

2

+1 về cách sử dụng mẫu nhà máy - rất mạnh mẽ ở đó.

Bên cạnh những mô hình nhà máy, mỗi khi tôi đã sử dụng nó, tôi có lẽ không nên có ...

Tôi đã sử dụng nó để tự động tải các lớp học mà thực hiện các giao diện nào đó (tôi là các mục menu từ hội đồng) lúc khởi động và tôi thực sự hối tiếc rằng việc sử dụng. Tôi muốn tôi sẽ được tải từ một tập tin cấu hình (và sau đó thêm một hình thức cho thấy giao diện có sẵn để tải). Thật thú vị nhưng cực kỳ chậm ...

Chống mẫu là sử dụng thuộc tính truy cập mà nhà thiết kế lớp được đánh dấu là riêng tư mà không biết tại sao họ đánh dấu chúng là riêng tư. Tôi đã thực hiện điều này với điều khiển DataGridView WinForms để bỏ đặt biến boolean để tôi có thể di chuyển cột "đồng hành" khi phần bổ sung của nó được di chuyển. Một lần nữa, nó rất mát mẻ nhưng mã đó sẽ thất bại khủng khiếp nếu một phiên bản mới thay đổi tài sản riêng tư (nó rất tốt có thể được đi trong 3.0 hoặc 3.5 ...).

6

tôi thấy phản ánh (kết hợp với lớp runtime tải) không thể thiếu cho các plugin thực hiện:

  1. tìm kiếm lọ/cụm ở một vị trí nổi tiếng
  2. lọ enumerate/hội cho các lớp học hỗ trợ giao diện plugin của bạn hỗ trợ
  3. khởi tạo plugin tại thời gian chạy
0

Phản ánh cho phép bạn giải quyết các vấn đề có thể yêu cầu bạn sao chép đồng de. Nếu bạn thấy mình đang sao chép và dán mã, và không thể thấy mẫu OO có thể trợ giúp như thế nào, có thể nếu bạn có thể gọi chúng, thì "nhóm r" có thể giúp bạn.

Chỉ nói đùa. Tôi không thể hiểu được điểm phản chiếu của các lứa tuổi. Nếu bạn có thể viết mã để thực hiện một công việc, tại sao bạn cần phải sử dụng sự phản chiếu?

Giả sử bạn có nhiều đối tượng GUI như Biểu mẫu hoặc đối tượng 'bảng'. Nó liên kết với một đối tượng kinh doanh như một Khách hàng:

public class Customer 
{ 
    public string FirstName; 
    public string LastName; 

} 

Người dùng của bạn không muốn thấy tiêu đề cột 'FirstName' hoặc 'LastName'. Họ muốn 'Tên Cơ đốc' và Họ. Bạn không muốn mã các chuỗi chữ trong tất cả các đối tượng GUI của bạn trong trường hợp họ thay đổi ý định thành 'First Name' và 'Father's last name' (tôi biết, ví dụ crap).

Nếu bạn xác định lớp sử dụng các thuộc tính của bạn:

public class Customer 
{ 
    [Description("Christian Name")] 
    public string FirstName; 

    [Description("Surname")] 
    public string LastName; 

} 

Bạn có thể sử dụng phản ánh để kéo ra khỏi các tên cột. Nếu bạn cần thay đổi cách tất cả đối tượng GUI của bạn mô tả đối tượng khách hàng, bây giờ bạn làm điều đó ở một nơi.

Tôi không biết về bất kỳ mẫu chống nào. Lời khuyên của tôi là nhảy vào và thử nó. Bạn sẽ bắt đầu thấy tất cả các loại cách thức phản chiếu mang lại cho bạn một giải pháp thanh lịch. Hiệu suất thường được trích dẫn như một lý do không sử dụng sự phản xạ. Có một hiệu suất trên không với sự phản đối nhưng tôi sẽ giảm giá nó trừ khi bạn có thể chứng minh chi phí đang làm tổn thương một thuật toán bạn cần.

+0

+1: Phản chiếu làm giảm trùng lặp mã. -1: Kiểm tra thời gian biên dịch là một lý do quan trọng hơn nhiều để không sử dụng sự phản chiếu. Phản ánh trong ví dụ này là một phần của khuôn khổ, không được nhà phát triển triển khai. Đối với bất kỳ phản ánh không được thực hiện trong khuôn khổ tôi nghiêm túc cố gắng suy nghĩ lại cách tiếp cận của tôi. Bạn sẽ thấy rằng các chuỗi ký tự chứa mã có thể khó bảo trì như mã trùng lặp mà bạn đã cố tránh. Ở đây tạo mã có thể là một lựa chọn tốt. –

+0

IMHO ví dụ của bạn là một mẫu chống. Sử dụng thuộc tính Description ở đây sẽ làm cho việc xử lý i18n gần như không thể.Bạn sẽ không chỉ phải dịch các biểu mẫu mà còn là mã. – Nux

8

Tôi đã sử dụng phản chiếu ở một số địa điểm. Các danh mục chính bao gồm:

  1. GUI được tạo tự động (ví dụ: trình chỉnh sửa thuộc tính). Bạn có thể lặp qua các thuộc tính của một đối tượng và sử dụng một registry của các nhà máy phần tử UI để xây dựng một biểu mẫu. Tôi sử dụng các thuộc tính trên các thuộc tính để hướng dẫn tạo giao diện người dùng.
  2. Nối tiếp. Tôi đã viết các khuôn khổ tuần tự hóa bằng cách sử dụng sự phản chiếu sử dụng để tuần tự hóa và deserialize các đối tượng.
  3. Dịch vụ web. Tương tự như tuần tự hóa, tôi đã sử dụng sự phản chiếu để tạo và tiêu thụ các thông điệp SOAP và cũng để tạo ra WSDL.
  4. Ngôn ngữ cụ thể tên miền. Các ngôn ngữ kịch bản được diễn giải thường sẽ liên kết với các đối tượng và các phương thức sử dụng sự phản chiếu.
  5. Công cụ gỡ lỗi. Các công cụ như vậy có thể sử dụng sự phản chiếu để kiểm tra trạng thái của một đối tượng. Tiện dụng để tạo thông điệp tường trình trong điều kiện lỗi.

Mẫu khôn ngoan, tôi không chắc chắn các mẫu là gì. Một chủ đề chung giữa tất cả các sử dụng là tham chiếu theo tên và ràng buộc trễ - bạn muốn liên kết với một thành viên trong thời gian chạy. Điều này thường xảy ra khi bạn nạp linh hoạt các assembly và không biết các loại objeccts bạn cần tạo/thao tác.

Sử dụng phản chiếu mạnh mẽ, nhưng nó sẽ không làm cho bạn phổ biến hơn ở các bên. Chỉ sử dụng nó khi khớp nối cố ý yếu. Vì vậy, yếu mà bạn mong đợi nó để phá vỡ trong thời gian chạy. Một ví dụ tuyệt vời là ràng buộc dữ liệu trong WPF.

Tôi không chắc chắn về chống mô hình, nhưng chắc chắn nó sẽ liên quan đến làm việc trong thời gian chạy mà nên được thực hiện tại thời gian biên dịch ...

1

Nơi Thủ tôi sử dụng phản ánh: Kéo một loại ra khỏi một cơ sở dữ liệu.

Tôi có một lớp học cần biết thư viện nào cần gọi. Hãy nhớ rằng khi các công cụ mới được thêm vào danh sách, lớp cần nhận ra các công cụ mới mà không cần biên dịch lại, vì vậy một câu lệnh chuyển đổi nằm ngoài câu hỏi. Thay vào đó, tôi lưu chuỗi phản chiếu trong DB để cho lớp biết "tạo một trong số này ..." Vì tôi (lập trình viên) luôn đảm bảo rằng lớp được bắt nguồn từ một lớp cơ sở duy nhất, ý tưởng hoạt động . Nó sạch sẽ và hiệu quả.

Nhưng tôi đồng ý rằng nếu bạn sử dụng phản ánh nhiều hơn các trường hợp "mã được tạo tự động" này, thì bạn có thể mở cửa cho một thế giới bị tổn thương khi nói đến việc duy trì mã trong tương lai.

(nhập tiếng nói khôn ngoan, hiền triết cũ)
Phản ánh đi kèm với sức mạnh đáng kinh ngạc ... sử dụng sức mạnh với trí tuệ.

0

Khi bạn muốn cải thiện hiệu suất của các đối tượng bị ràng buộc trễ. Bạn có thể phát ra mã cần thiết để gọi trực tiếp các loại ràng buộc, và sau đó gọi thông qua phương thức được phát ra của bạn. Mặc dù bạn không thể thực hiện các cuộc gọi một cách nhanh chóng như với sự ràng buộc sớm, nhưng bạn sẽ thực hiện tốt hơn so với kết buộc muộn.

0

Tôi personaly không sử dụng nó nhiều. Tôi có xu hướng sử dụng nó khi tôi không có cách nào khác để viết mã.

Dưới đây là một ví dụ đơn giản:

public static void LogException(Exception exc, string source) 
{ 
    try 
    { 
     // Logic for logging exceptions 
    } 
    catch(Exception ex) 
    { 
     //If logging fails for some reason 
     //then we still log it using reflection 
     LogException(ex, "Error while logging an exception"); 
    } 
} 
Các vấn đề liên quan