Làm thế nào có thể tiêm phụ thuộc vào ngôn ngữ? [đóng cửa]


10

Tôi đã suy nghĩ một chút về cách tiêm phụ thuộc có thể được tích hợp tốt hơn trực tiếp vào ngôn ngữ như C #. Tôi đã đưa ra một giải pháp tiềm năng mà tôi muốn nghe ý kiến ​​của bạn. Tôi chưa sử dụng nhiều khung tiêm phụ thuộc nên có thể có thứ gì đó tôi đang xem

Dù sao, ý tưởng là có thể khai báo các thuộc tính là "tiêm" bằng cách sử dụng từ khóa. Khi một đối tượng được khởi tạo và thuộc tính đó không được khởi tạo thông qua hàm tạo hoặc trình khởi tạo đối tượng, nó yêu cầu một thể hiện của loại thuộc tính đó từ một số dịch vụ toàn cầu.

Tương tự, bạn đăng ký trình xử lý cho các loại khác nhau cho dịch vụ đó để bạn có thể khởi tạo loại thuộc tính được tiêm.

Ưu điểm của việc sử dụng loại kiến ​​trúc IMO này là nó khá linh hoạt và dễ sử dụng. Nhược điểm là có thể có một số chi phí thực hiện chú thích cho người độc thân mỗi khi bạn bắt đầu một lớp đã tiêm.

Sau đó, một lần nữa, đó chỉ là một vấn đề đối với các lớp được khởi tạo thường xuyên trong một giải pháp hiệu suất cao, vì vậy nó không phải là vấn đề lớn. Có lẽ bạn có thể sử dụng một số loại nhà máy trong những trường hợp đó.

Suy nghĩ, vấn đề, câu hỏi, ý tưởng tốt hơn?

public class SomeClass
{

  public SomeClass()
  {
     //implicit behavior if Animal is not set in constructor or initializer
    this.Animal =  GlobalInjector.Get(this,typeof(Mammal))

  }

  public injectable Mammal Animal  
  {
   get;
   set;
  }
}


 GlobalInjector.Register(typeof(Mammal), () => return new Mammal(someParameter));

Bạn có thể đưa ra một ví dụ mã giả cho những người trong chúng ta không quen thuộc với DI? Tái bút Có lẽ bạn có thể trả lời câu hỏi của tôi về DI là tốt? :)
Steven

2
Tôi không chắc là tôi có được nó. Bạn có thể nhận được tất cả những thứ đó với bộ chứa DI toàn cầu và thuộc tính '[Tiêm] thay vì từ khóa, phải không?
nikie

Xin chào, tôi đã thử viết một chút về DI về câu hỏi của bạn, không chắc là nó trả lời mặc dù
Homde

nikie: Vâng chắc chắn, tôi đoán bạn có thể thực hiện cơ chế thực tế theo nhiều cách khác nhau, tôi quan tâm hơn nếu logic cơ bản là âm thanh
Homde

Vậy có gì khác biệt giữa cái này và IoC hiện tại ngoài từ khóa phụ của bạn?
Matthew Whited

Câu trả lời:


7

Có những thứ thuộc về ngôn ngữ và những thứ không. Từ lâu, C đã nhận ra rằng IO không thuộc về ngôn ngữ vì nó nằm ngoài mô hình điện toán và có thể được thực hiện với các thư viện hàm.

Phụ thuộc tiêm là như thế. Nó nằm ngoài ngôn ngữ và có thể được thực hiện với các khung phù hợp.

Một trong những vấn đề với các ngôn ngữ hiện đại là họ cố gắng làm quá nhiều. Cuối cùng, những ngôn ngữ đó sụp đổ dưới sức nặng của chính họ khi các lập trình viên chạy đến những ngôn ngữ đơn giản hơn.


Tôi đồng ý về mặt lý thuyết, bạn không thể có một ngôn ngữ mà mọi chức năng là một tính năng của ngôn ngữ mà không bị bồng bềnh. Tuy nhiên, luôn có chỗ cho những trừu tượng mới cao hơn giúp chúng ta viết mã tốt hơn. Có lẽ tiêm phụ thuộc mỗi lần không phải là vấn đề cần giải quyết mà là vấn đề mà nó giải quyết, cụ thể là cách giúp chúng tôi giảm bớt sự phụ thuộc dễ dàng hơn. Đây có thể không phải là cách tốt nhất để làm điều đó :)
Homde

5

Nó không cần thiết

Một trong những điều tôi thích nhất về các khung DI tốt nhất mà tôi đã sử dụng là mã cấu hình cấp cao nhất là phần duy nhất trong mã của bạn cần biết về DI. Tự động nối dây được thực hiện ở cấp độ chứa và cấu hình / "tải mô-đun" và mã ứng dụng của bạn có thể hoàn toàn không biết gì về nó.

Điều này có nghĩa là không có thuộc tính, không có chuỗi ma thuật, không có quy ước. Mỗi đoạn mã chỉ biết rằng nó chấp nhận mã trong hàm tạo (/ property / phương thức) của nó và đó là tất cả.

Với một thiết kế như vậy, bạn không cần phải thay đổi ngôn ngữ để hỗ trợ Dependency Injection.

Nó có khả năng nguy hiểm

Điều tôi sợ nhất về một hệ thống tiêm phụ thuộc tích hợp ngôn ngữ là nó sẽ tạo ra một rào cản chống lại bất kỳ triển khai nào khác, nhưng nó có thể sẽ tự vẽ vào một góc trong một khía cạnh nào đó.

Một số cách nó có thể tự vẽ vào một góc:

  • Chỉ hỗ trợ cấu hình dựa trên XML hoặc chỉ cấu hình dựa trên mã
  • Không thể hỗ trợ sạch mẫu thiết kế của Nhà máy (không chỉ các thành phần nhất thời: các thành phần được tạo trong thời gian chạy)
  • Bằng cách nào đó thay đổi mã của tôi để tôi buộc phải sử dụng phép nội xạ phụ thuộc và không thể đơn giản khởi tạo lớp của mình để kiểm tra đơn vị
  • Không hỗ trợ vòng đời tùy chỉnh
  • Không thể mở rộng
  • Không thể thay thế trong trường hợp tôi cần tùy chỉnh lớn hơn
  • Bị phá vỡ theo một cách nào đó mà chúng ta chưa hiểu, bởi vì chúng tôi. Người dùng Net đã không sử dụng DI đủ lâu để biết những cạm bẫy

4

Bạn đã thấy Khung mở rộng được quản lý đi kèm với .NET 4 chưa? Đây là một bài báo tôi đã viết với một số ví dụ. Về cơ bản, đây là một hình thức tiêm phụ thuộc được tích hợp vào .NET, với các tính năng bổ sung về khả năng khám phá trong thời gian chạy.

Tiêm tài sản trông như thế này:

class Program
{
    [Import]
    public IMessageSender MessageSender { get; set; }
}

Con tiêm xây dựng trông như thế này:

class Program
{
    [ImportingConstructor]
    public Program(IMessageSender messageSender) 
    {
    ...
    }
}

Bạn có thể nhập các trường, nhập tùy chọn, nhập bộ sưu tập dịch vụ, bao gồm cả việc lười nhập bằng siêu dữ liệu để bạn có thể tìm kiếm một dịch vụ phù hợp để khởi tạo. Bạn thậm chí có thể nhập lại vào thời gian chạy để tìm kiếm các tiện ích mở rộng mới.


Mặc dù MEF thực sự tuyệt vời cho các công cụ bổ trợ, tôi không nghĩ rằng tôi muốn sử dụng nó như một cơ chế DI chung
Homde 30/03/2016

1
@MKO - Bạn có thể nói rõ hơn về những gì nó thiếu? Tôi biết tất cả các bài báo trong đó các cuộc đua của Glenn Block để trấn an mọi người rằng MEF sẽ không thay thế tất cả các khung DI, nhưng nếu bạn nhìn vào chi tiết, rõ ràng đó là một tuyên bố chính trị hơn bất kỳ điều gì khác. Tuy nhiên, nếu bạn có thể đưa ra một danh sách tốt các tính năng mà MEF thiếu so với các khung DI khác, điều đó sẽ giúp mọi người đưa ra quyết định sáng suốt. Ngoài ra, câu hỏi là về các khung DI trong C # và MEF rõ ràng là một thùng chứa DI trong khung .NET.
Scott Whitlock

2
  1. Bạn không thực sự mô tả cơ chế cấu hình, mà IMHO là một mẹo nhỏ. Làm thế nào để bạn thực hiện tất cả mã đang chạy trong một luồng sử dụng kết nối DB A, và tất cả mã trong kết nối luồng B khác? Làm thế nào để bạn chặn việc tiêm một tài nguyên nhất định, bởi vì người dùng hiện đang đăng nhập không được phép truy cập vào tài nguyên đó?
  2. Đừng sử dụng kim phun toàn cầu. Không sử dụng bất kỳ thứ gì trên toàn cầu, hoặc bạn cũng có thể sử dụng các biến toàn cục. Không, sử dụng OOP-speak như singleton hoặc "static" thay vì global không thay đổi bản chất toàn cầu của chúng.
  3. Hãy xem xét một container phạm vi năng động. Mặc dù phạm vi từ vựng đã chiến thắng một cách hợp lý chống lại phạm vi động, tôi tin rằng phạm vi động sẽ thay thế tốt cho phạm vi toàn cầu. Kế thừa khác biệt sẽ là một triển khai tốt đẹp (như trong kế thừa dựa trên nguyên mẫu).
  4. Tôi tin rằng một cơ chế DI được ủy quyền bằng ngôn ngữ nên thực sự đơn giản, không có công cụ enterprisey nào là chuẩn mực trong C # và Java. Một cơ chế phạm vi động với lớp cấu hình đơn giản ở trên có thể thực hiện thủ thuật. Các giải pháp Enterprisey có thể được các bên thứ ba xếp lên hàng đầu.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.