Ninject la gi

Bend software to your will

Stop writing monolithic applications that make you feel like you have to move mountains to make the simplest of changes. Ninject helps you use the technique of dependency injection to break your applications into loosely-coupled, highly-cohesive components, and then glue them back together in a flexible manner.

Laugh in the face of change

Change is inevitable, so be prepared. Ninject allows you to embrace change in your software's design, so it will be easier to adjust it to match changing business needs and expectations. Then, the next time someone asks for a "small" change to your application, you can laugh in triumph rather than quivering in pain.

Use your sharpest tools

Once you break your application into components, you have to glue them back together. Rather than depending on a bunch of XML to describe how the pieces fit together, Ninject uses a powerful fluent interface. This lets you get the most out of the sharpest tools in your arsenal: your compiler and your IDE.

Write smarter software everywhere

Dependency injection isn't just for big enterprise applications; with the right framework, you can apply the practice to improve software projects of all sizes and types. Ninject was designed to be ultra-lightweight and universal. It also runs practically anywhere, including on Mono, the .NET Compact Framework, and Silverlight.

Be fast, be agile, be precise

Ninject makes dependency injection so easy that it becomes hard not to follow good practices. Once you start writing your applications with dependency injection in mind, your code will be easier to understand, easier to change, and less error-prone. Simply put, Ninject makes your application more ninja-like!

Write your code so it's flexible...

				public class Samurai {
					public IWeapon Weapon { get; private set; }
					public Samurai(IWeapon weapon) 
					{
						this.Weapon = weapon;
					}
				}
			

...and let Ninject glue it together for you.

				public class WarriorModule : NinjectModule
				{
					public override void Load() 
					{
						this.Bind().To();
					}
				}
			

Why is Ninject useful?

The vast majority of effort that is invested in software happens after the initial release. Because Ninject makes your software much easier to change, a small up-front time investment will pay huge dividends as time goes on.

What makes Ninject different?

An obsessive focus on simplicity and ease of use. We've seen the value of dependency injection, but were frustrated by the complexity of existing solutions. The goal of Ninject is make dependency injection accessible to all developers and all projects.

How much does it cost?

Ninject is and will always be free for both personal and commercial projects. It's also open source, so you can fork the code and make any changes you like. (We appreciate it if you share anything useful you come up with us, though!)

Như các bạn đã biết thì Dependency Injection là một mẫu thiết kế để giảm sự phụ thuộc của các module. Có rất nhiều thư viện hỗ trợ chúng ta triển khai việc này. Ninject là một thư viện khá hay, và dễ sử dụng. Hãy cùng xem ví dụ sau và các áp dụng Ninject như thế nào?

Chúng ta bắt đầu với ví dụ send email:

public interface IConfirmationMessageSender
{
   void Send(string message, string email);
}


public class EmailMessageSender: IConfirmationMessageSender
{   
   public void Send(string message, string email)
   { 
     Console.WriteLine("Email recipient={0} : data={1}", email,message);
   }
}

public class MessageSender
{ 
   // a lot of complicated stuff here :)
   // ..
   // ..
  
   public void SendMessage(string message, string email)
   {
     EmailSender emailSender = new EmailSender(); 
     emailSender.Send(message,recipient); 
   } 

   // ..
   // ..

}

class Program
{   
   void Main(string[] args)
   {
      MessageSender messageSender = new MessageSender();
      messageSender.SendMessage("Some text","[email protected]"); 
   }
}

Đoạn code trên khá dễ hiểu, tuy nhiên lại có một số vấn đề về như sau:

  1. Extensible isssue: Nếu như trong quá trình phát triển, chúng ta cần thêm một channel để gửi thông tin ví dụ SMS thì việc thay đổi là không dễ dàng.

  2. Coupling issue: Trong ví dụ này MessageSender class sẽ bị phụ thuộc trực tiếp vào EmailSender class.

  3. Testability issue: Nếu giả sử bạn cần test class MessageSender độc lập thì nó vi phạm tư tưởng của Unit testing đó là việc có thể tiến hành test các method hay component một cách độc lập

Để giải quyết vấn đề trên thì đây là lúc chúng ta nghĩ đến Dependency Injection. Mục đích là làm giảm sự phụ thuộc giữa các class, component.

Hãy thử triển khai thêm dịch vụ gửi SMS và kiến trúc lại hệ thống:

public interface IConfirmationMessageSender
{
   void Send(string message, string recipient);
}

public class EmailMessageSender: IConfirmationMessageSender
{   
   public void Send(string message, string recipient)
   { 
     Console.WriteLine("Email recipient={0} : data={1}", recipient,message);
   }
}

public class SMSMessageSender: IConfirmationMessageSender
{   
   public void Send(string message, string recipient)
   { 
     Console.WriteLine("SMS recipient={0} : data={1}", recipient,message);
   }
}

public class MessageSender
{
 IConfirmationMessageSender _messageSender = null;

 public MessageSender(IConfirmationMessageSender messageSender)
 {
   _messageSender = messageSender;
 }

 public void SendMessage(string message, string recipient) 
 { 
   _messageSender.Send(message,recipient); 
 } 
}

Và sử dụng SMS sensder như sau:

class Program
{   
   void Main(string[] args)
   {
      IConfirmationMessageSender confirmationMessage = new SMSMessageSender();
      MessageSender messageSender = new MessageSender(confirmationMessage); 
      messageSender.SendMessage("Some text","123456789");
      Console.ReadKey(); 
   } 
}

Với việc tổ chức code lại như trên chúng ta đã giải quyết được issue như:

  1. Extension: Nếu như cần thay đổi cách thức để gửi message, chúng ta có thể dễ dang thay đổi hay mở rộng. Và quan trọng là việc thay đổi không vi phạm nguyên tắc Open-Close principle.

  2. Testability: chương trình cho phép ta có thể test class MessageSender với bất cứ kiểu communication nào (EmailSender, SMSSender, etc.)

  3. Tight coupling: sự phụ thuộc giữa MessageSender và EmailMessageSender class đã được giải quyết.

Tuy nhiên chúng ta có thể làm cho việc triển khai dễ dàng hơn bằng cách sử dụng Ninject Framework. Ở đây chúng ta sẽ không đi quá chi tiết vào Ninject mà chỉ xem xét cách ứng dụng Framework này như thế nào:

Step1: chúng ta sẽ định nghĩa một Binding class như sau:

using Ninject;
using Ninject.Modules;
public class Bindings: NinjectModule
{   
   public override void Load()
   { 
     Bind().To(); 
   } 
}

Ý tưởng ở đây là khai báo để Ninject biết mapping giữa interface và một implementation cụ thể. Nếu như muốn thay đổi cách thức gửi message chúng ta chỉ cần thay đổi mapping, mà gần như không phải thay đổi code trong hệ thống. Great!!!!!!!!!!!!!!!