5

Tôi biết rằng hàng nghìn câu hỏi liên quan đến chủ đề này đã được hỏi, nhưng tôi đã trải qua ít nhất một tá và vẫn chưa kết nối các dấu chấm. Tôi đang cố gắng để thiết lập tiêm phụ thuộc cho bối cảnh thực thể.Ninject: Ngữ cảnh thực thể đối với bộ điều khiển

Tôi đã luôn luôn tạo ra bối cảnh thực thể của tôi như tôi đã thấy trong các hướng dẫn MS, như vậy:

public class UserController : Controller 
{ 
    private DbEntities db = new DbEntities(); 

} 

đọc gần đây đã nói với tôi rằng đây là không còn (nếu nó bao giờ là) các thực hành tốt nhất, và phương pháp tiêm phụ thuộc nên được sử dụng. Ninject được đề cập thường xuyên, nhưng tôi thấy cách bạn di chuyển từ những gì tôi có, đến ví dụ đưa ra trong số Ninject documentation.

Nó sẽ giống như thế này khi tôi làm xong, phải không?

public class UserController : Controller 
{ 
    private DbEntities db; 

    public UserController(DbEntities context) 
    { 
     db = context; 
    } 
} 

Tài liệu bắt đầu bằng "Ở bước trước, chúng tôi đã chuẩn bị mọi thứ cần thiết cho việc điều khiển tiêm". điều gây nhầm lẫn là địa ngục, vì bước trước đã được cài đặt. Tôi đã sử dụng phương pháp Nuget để cài đặt, nhưng tôi không biết ý nghĩa của nó khi nói "Bây giờ tải các mô-đun của bạn hoặc xác định các ràng buộc trong phương thức RegisterServices." Làm thế nào để làm điều đó, và là thực thể một mô-đun hoặc một ràng buộc? Các tài liệu cảm thấy rất thưa thớt.

Tôi xin lỗi nếu tôi bỏ qua thứ gì đó quan trọng trong tài liệu, tôi đã nảy ra giữa các diễn đàn trong nhiều giờ để tìm ra bước này.

Trả lời

4

tôi đã sử dụng phương pháp NuGet để cài đặt, nhưng tôi không biết những gì nó có nghĩa là khi nó nói "Bây giờ nạp module của bạn hoặc xác định các ràng buộc trong phương pháp RegisterServices." Làm thế nào để tôi làm điều đó, và là một thực thể một mô-đun hoặc một ràng buộc?

Cài đặt Nuget thực sự thực hiện khá nhiều thứ cho bạn. Điều quan trọng nhất là nó thiết lập Ninject là nhà máy điều khiển, có nghĩa là Ninject sẽ tạo các bộ điều khiển của bạn và có thể truyền vào tất cả các phụ thuộc bạn đã đăng ký với nó.

Nếu bạn kiểm tra thư mục App_Start, bạn sẽ tìm thấy tệp NinjectMVC3.cs. Đã có một phương thức trống RegisterServices() mà bạn có thể sử dụng để đăng ký các phụ thuộc của mình.

Ví dụ của bạn, bạn phải có khả năng giải quyết DbEntities. Các đơn giản nhất cách cơ bản nhất để làm điều này là:

kernel.Bind<DbEntities>().ToSelf(); 

Điều đó nói rằng bạn thực sự cần vượt qua trong một giao diện để điều khiển của bạn để điều khiển không phụ thuộc vào Entity Framework, sử dụng trừu tượng và đăng ký một lớp học cụ thể để sử dụng trong Container IoC là một trong những lý do chính để tiêm phụ thuộc.

Điều này sẽ giúp bạn bắt đầu - tài liệu bạn liên kết có vẻ hơi lỗi thời. Tôi khuyên bạn nên xem số Ninject MVC3 sample trên github.

+0

Cảm ơn bạn. Tôi đã tải xuống mẫu, nhưng nó có quá nhiều thứ đang diễn ra trong đó khiến cho khó có thể biết được những gì đang làm.Tôi không hiểu làm thế nào ràng buộc đang làm việc vẫn còn, nhưng dòng đó có vẻ là tất cả phải mất để cung cấp cho các nhà xây dựng của bộ điều khiển bối cảnh. Bạn có thể giới thiệu bất kỳ bài viết hoặc hướng dẫn nào thực sự giải thích những gì đang xảy ra ở đây không? – Tyrsius

+0

Tôi sẽ kiểm tra các liên kết trên 'http: // ninject.org/learn', cũng nói chung để tiêm phụ thuộc, hãy xem cuốn sách" Dependency Injection in .NET "của Mark Seemann – BrokenGlass

1

Tính phụ thuộc Tiêm lúc đầu có vẻ khó hiểu, nhưng thực sự thực sự khá đơn giản.

Một Dependency Injection "container" về cơ bản là một nhà máy chung, với các tính năng quản lý lâu dài đối tượng khác nhau. Cụ thể, Ninject sử dụng cú pháp kernel.Bind() để kết hợp nhà máy này.Khi bạn nói kernel.Bind<DbEntities>().ToSelf() điều này có nghĩa là Ninject sẽ tạo ra một thể hiện của kiểu ràng buộc (DbEntities trong trường hợp này) bất cứ khi nào kiểu đó được yêu cầu. Yêu cầu này thường trông giống như sau:

var entities = kernel.Get<DbEntities>(); // Note: don't do this, just an example 

Ở cốt lõi, đây là những gì Dependency Injection là. Một nhà máy chung có thể khởi tạo các loại tùy ý.

Tuy nhiên, có nhiều điều hơn thế nữa. Một tính năng thú vị của Dependency Injection là nó cũng sẽ khởi tạo bất kỳ kiểu phụ thuộc nào trong tiến trình. Vì vậy, giả sử bạn có một bộ điều khiển, và bộ điều khiển đó có một sự phụ thuộc vào DbEntities. Vâng, khi một bộ điều khiển được khởi tạo bởi DI Framework, nó cũng sẽ khởi tạo DbEntities phụ thuộc. Xem mã bên dưới. Khi MyController được khởi tạo, các DbEntities sẽ tự động được khởi tạo (giả sử bạn đã bị ràng buộc lớp DbEntities tự trong Configuration DI)

var controller = kernel.Get<MyController>(); 

public class MyController : Controller { 
    private DbEntities _entities; 
    public MyController(DbEntities entities) { 
     _entities = entities; 
    } 
} 

Đây là đệ quy. Bất kỳ lớp nào được khởi tạo mà có bất kỳ đối tượng nào mà bản thân nó có thể phụ thuộc vào cũng được khởi tạo, vân vân, và vân vân cho đến khi cuối cùng, mọi thứ đều cần làm công việc của nó.

Bây giờ, điều tuyệt vời về MVC là nó có cách tích hợp để sử dụng bất kỳ vùng chứa DI nào một cách tự động. Bạn không cần phải gọi kernel.Get vì khung làm việc đó cho bạn khi nó tạo bộ điều khiển khi có yêu cầu. Tính năng này được gọi là IDependencyResolver và là giao diện mà khung MVC sử dụng để cho phép sử dụng vùng chứa DI bên thứ ba theo khuôn khổ.

Nếu bạn cài đặt Ninject bằng cách sử dụng gói NuGet Ninject.MVC3 sau đó nó sẽ tự động cấu hình tất cả điều này cho bạn, và bạn chỉ cần thêm các ràng buộc của mình vào RegisterServices() phần của NinjectMVC3.cs

Có rất nhiều nhiều hơn thế, nhưng điều này sẽ cho bạn một sự hiểu biết cơ bản. Dependency Injection cho phép bạn quên các chi tiết về quản lý khi các đối tượng được tạo và hủy, bạn chỉ cần xác định trong constructor của bạn mà bạn cần, và giả sử bạn có bindings cho chúng trong cấu hình của bạn, MVC sẽ chăm sóc tạo và hủy chúng bạn. Bạn chỉ cần sử dụng chúng.

EDIT:

Để rõ ràng, tôi không khuyên bạn sử dụng các ví dụ tôi đưa ra ở trên. Họ chỉ là minh họa đơn giản về cách DI hoạt động. Cụ thể, cú pháp Get() được gọi là "Vị trí dịch vụ" và được coi là xấu. Tuy nhiên, cuối cùng một số mã, một nơi nào đó phải gọi Get(), nó chỉ được chôn sâu trong khuôn khổ.

Như Adam đề cập, ràng buộc trực tiếp với bối cảnh thực thể dữ liệu không phải là một ý tưởng tuyệt vời và cuối cùng bạn nên chuyển sang sử dụng phương pháp tiếp cận dựa trên giao diện.

+0

ràng buộc bộ điều khiển cho dữ liệu cụ thể truy cập thực hiện trong khi sử dụng tiêm phụ thuộc? –

+0

@AdamTuliper - đó là những ví dụ đơn giản về những gì diễn ra trong khung công tác. Lý tưởng nhất là sử dụng giao diện, nhưng tôi không muốn tăng tính phức tạp của ví dụ. Khung chính nó sẽ khởi tạo bộ điều khiển, nhưng sử dụng thùng chứa DI được định cấu hình để giải quyết các kiểu được tiêm, do đó, nó giống như chính bộ điều khiển đã bị ràng buộc. –

+0

@MyerstereMan, Cảm ơn bạn, điều này rất thông tin. Để làm rõ: vì việc triển khai Ninject của MVC3 thiết lập 'IDependencyResolver' cho bạn,' .Get() 'không bao giờ cần thiết? Liệu '.Get()' có được sử dụng trong các khung máy tính để bàn không? – Tyrsius

0

Tôi sẽ không bao giờ tiêm loại bê tông ở đây - bạn đang trực tiếp ghép nối với triển khai truy cập dữ liệu.

Thay vào đó liên kết với IDbContext (hoặc IUnitOfWork) - đây là giao diện bạn xác định với triển khai DbContext, cách này bạn có thể dễ dàng loại bỏ công nghệ bạn đang sử dụng, làm cho nó dễ thay đổi, có thể kiểm tra, bảo trì, v.v.

cho ví dụ: http://blogs.planetcloud.co.uk/mygreatdiscovery/post/EF-Code-First-Common-Practices.aspx#disqus_thread

+0

Tôi đồng ý với hiệu trưởng, nhưng ràng buộc với một loại cụ thể là một cách hay để tìm hiểu các khái niệm cơ bản về DI mà không cần phải nghiên cứu kỹ các triển khai giao diện. –

+0

@AdamTuliper Tôi sẽ phải đọc bài viết này sau, nhưng giải pháp này đòi hỏi nhiều công việc hơn. Tôi không hiểu làm thế nào tôi có thể gọi bộ thực thể cụ thể (bảng sql) trên bối cảnh của tôi từ bộ điều khiển mà không cần ghép nối với một thực hiện cụ thể. – Tyrsius

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