2009-06-30 31 views
9

Khi tạo thành phần .NET có thể thiết kế, bạn được yêu cầu cung cấp hàm tạo mặc định. Từ các tài liệu IComponent:Cách kết hợp các thành phần có thể thiết kế với việc tiêm phụ thuộc

Để trở thành một thành phần, một lớp phải thực hiện các giao diện IComponent và cung cấp một constructor cơ bản mà không cần tham số hoặc một tham số duy nhất của loại iContainer.

Điều này khiến không thể thực hiện việc tiêm phụ thuộc thông qua các đối số của hàm tạo. (Constructors tắm có thể được cung cấp, nhưng các nhà thiết kế sẽ bỏ qua chúng.) Một số lựa chọn thay thế, chúng tôi đang cân nhắc:

  • Service Locator

    Đừng sử dụng dependency injection, thay vì sử dụng các mô hình dịch vụ định vị để có được sự phụ thuộc. Điều này có vẻ là những gì IComponent.Site. GetService dành cho. Tôi đoán chúng ta có thể tạo một triển khai ISite có thể tái sử dụng (ConfigurableServiceLocator?) Có thể được cấu hình với các phụ thuộc cần thiết. Nhưng làm thế nào điều này làm việc trong một bối cảnh thiết kế?

  • Dependency Injection thông qua thuộc tính

    Tiêm phụ thuộc qua các thuộc tính. Cung cấp các trường hợp mặc định nếu chúng là cần thiết để hiển thị thành phần trong thiết kế . Tài liệu có thuộc tính cần được tiêm.

  • Tiêm phụ thuộc với một phương pháp Initialize

    Đây là giống như tiêm qua thuộc tính nhưng nó giữ danh sách các phụ thuộc mà cần phải được tiêm ở một nơi. Bằng cách này, danh sách các phụ thuộc bắt buộc được ghi lại hoàn toàn, và trình biên dịch sẽ hỗ trợ bạn với các lỗi khi danh sách thay đổi.

Bất kỳ ý tưởng nào là phương pháp hay nhất ở đây? Bạn làm nó như thế nào?


chỉnh sửa: Tôi đã gỡ bỏ "(ví dụ một WinForms UserControl)" kể từ khi tôi có ý định câu hỏi để được về thành phần nói chung. Các thành phần là tất cả về đảo ngược kiểm soát (xem phần 8.3.1 của UMLv2 specification) vì vậy tôi không nghĩ rằng "bạn không nên tiêm bất kỳ dịch vụ" là một câu trả lời tốt.


chỉnh sửa 2: Phải mất một số chơi với WPF và mô hình MVVM để cuối cùng "nhận được" câu trả lời của Mark. Tôi thấy rằng các điều khiển trực quan thực sự là một trường hợp đặc biệt. Đối với việc sử dụng các thành phần không nhìn thấy trên bề mặt thiết kế, tôi nghĩ mô hình thành phần .NET cơ bản không tương thích với việc tiêm phụ thuộc. Dường như nó được thiết kế xung quanh mẫu định vị dịch vụ thay thế. Có lẽ điều này sẽ bắt đầu thay đổi với cơ sở hạ tầng đã được thêm vào .NET 4.0 trong không gian tên System.ComponentModel.Composition.

Trả lời

6

Câu hỏi tương tự này đã làm tôi thất vọng trong một thời gian dài cho đến khi tôi nhận ra rằng tôi đang nghĩ về nó một cách sai lầm.AFAIR, lý do duy nhất để creaing một IComponent thực hiện là cung cấp các tính năng thiết kế thời gian - không có hiệu ứng thời gian chạy của việc triển khai IComponent.

Bằng cách sửa lỗi, điều này có nghĩa là bạn chủ yếu nên tạo các thành phần để triển khai các tính năng thiết kế thời gian. Riêng đối với Kiểm soát, điều này có nghĩa là bạn có thể định cấu hình thành phần hoạt động theo một cách nhất định. Nó là rất quan trọng để nhận ra rằng đây là một mối quan tâm hoàn toàn khác nhau hơn so với cách các thành phần thực sự cư xử hoặc dữ liệu nó hiển thị. Nó không nên có hành vi tại thời gian thiết kế, và cũng không nên chứa dữ liệu.

Như vậy, ràng buộc trên hàm tạo thực sự là một phước lành, vì nó chỉ thị cho bạn suy nghĩ lại thiết kế của bạn. Kiểm soát là phần phần mềm bất khả tri nguồn dữ liệu so với hiển thị và tương tác với dữ liệu theo một cách nhất định. Miễn là dữ liệu đó tuân theo một số giao diện nhất định, v.v. Cách dữ liệu đó đến không quan tâm đến Kiểm soát và cũng không phải là dữ liệu. Nó sẽ là một lỗi để cho phép kiểm soát kiểm soát cách dữ liệu được tải và sửa đổi.

Trong WPF, điều này rõ ràng là rõ ràng hơn nhiều so với trong Windows Forms: Bạn cung cấp cho một điều khiển cụ thể một DataContext và ràng buộc thuộc tính của điều khiển cho các thành viên của DataContext đó. DataContext (có thể là bất kỳ đối tượng nào) bắt nguồn từ bên ngoài Control; đó là trách nhiệm hoặc lớp trình bày của bạn.

Trong Windows Forms, bạn vẫn có thể thực hiện tương tự bằng cách gán ngữ cảnh dữ liệu cho Kiểm soát. Về cơ bản, đây là thuộc tính tiêm - chỉ cần lưu ý rằng bạn không nên tiêm dịch vụ; bạn nên tiêm dữ liệu.

Tóm lại, tôi sẽ không đi kèm với các đề xuất của bạn. Thay vào đó, hãy để Control có một hoặc nhiều thuộc tính cho phép bạn gán dữ liệu cho Control, và sử dụng databinding để liên kết với dữ liệu này. Bên trong việc thực hiện của Control, được chuẩn bị để xử lý tình huống không có dữ liệu: Điều này sẽ xảy ra mỗi khi Control được lưu trữ bởi VS tại thời điểm thiết kế. Mô hình đối tượng Null rất hữu ích cho việc thực hiện khả năng phục hồi này.

Sau đó, thiết lập ngữ cảnh dữ liệu từ Bộ điều khiển của bạn. Đó là cách MVC để làm điều đó: Control là View, nhưng bạn nên có một Controller riêng biệt có thể khởi tạo và gán một Model cho View.

+0

Nếu tôi giải thích câu trả lời của bạn một cách chính xác, bạn đang nói rằng các điều khiển không được sử dụng bất kỳ dịch vụ nào. Tôi không chắc tôi đồng ý. Ví dụ, tôi có một điều khiển mà không hiển thị văn bản trực tiếp bằng cách gọi System.Windows.Forms.TextRenderer. Thay vào đó, nó sử dụng một dịch vụ ITextRenderer được tiêm (với các phương thức cơ bản giống nhau). Điều này cho phép tôi thực hiện các chiến lược viết tắt ưa thích vượt ra ngoài những gì được cung cấp bởi khung công tác .NET, trong khi vẫn giữ mã như vậy độc lập khỏi bản thân kiểm soát. –

+0

Có, tôi nói rằng Điều khiển không nên sử dụng dịch vụ - dịch vụ nên sử dụng Điều khiển. Điều khiển không nên làm gì ngoài giao diện người dùng. Nó là tốt mà bạn có thể tiêm chiến lược viết tắt ưa thích, nhưng logic như vậy thuộc về (View) Model, không phải trong View chính nó. Sau đó bạn có thể databind View của bạn thành các thuộc tính trên mô hình tạo ra các giá trị mong muốn bằng cách gọi các phụ thuộc được tiêm. Mặc dù bạn dường như đang sử dụng WinForms, hãy kiểm tra điều này để lấy cảm hứng: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx –

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