Introduction
This post discusses dependency Injection (DI) with example of email providers. Dependency Injection is a simple way to load plugins dynamically.
Background Of DI
Basically, Dependency injection is a technique for building loosely coupled applications. First, let's see what is tight & loose coupling.
Tight coupling - classes and objects are dependent on one another. Tight coupling is usually bad because it reduces flexibility and re-usability of code and it makes changes much more difficult and impedes test-ability. Loose coupling is a more generic concept, intended to increase the flexibility of a system. It makes the system more maintainable and makes the framework more "stable", also it improves test-ability.
With dependency injection, we can achieve a plug-in architecture with minimum dependencies between objects.
There are three options in order to perform dependency injection:
- Constructor Injection: Constructing a new instance of an object we inject the dependencies. Dependencies can be passed in the constructor.
- Setter Injection: Component exposes a setter method or property which we will inject a dependency to it.
- Method Injection: Dependencies can supply via a method parameter
In the below code sample using example of email providers, we will see how we can implement the above 3 DI injections.
Using the Code
I have attached the source code of this application, here I have created ASP.NET website, and implemented functionality of email sending with email server as SMTP or GMail; by using Dependency Injection pattern.
IEmailService.cs - Here, first we will require injector as interface IEmailService
. This interface defines the method that is used to inject one or more dependencies.
public interface IEmailService
{
bool SendMail(EmailInfo Obj);
}
clsEmailInfo.cs - Here, I have taken one common EmailInfo
class - where we can set email information properties like From, To, CC, Bcc, etc.
public class EmailInfo
{
}
clsSMTPProvider.cs - This is an actual implementation of Email sending using SMTP as server. Here, we have implemented the IEmailService
interface to allow objects to be injected. And we put email sending logic here.
public class SMTPProvider : IEmailService
{
public bool SendMail(EmailInfo emailInfo)
{
MailMessage message = new MailMessage();
message.To.Add(emailInfo.To);
message.Subject = emailInfo.Subject;
message.From = new System.Net.Mail.MailAddress(emailInfo.From);
message.Body = emailInfo.Body;
SmtpClient smtp = new SmtpClient("localhost");
try
{
smtp.Send(message);
return true;
}
catch (Exception ex)
{
return false;
}
}
}
clsGmailProvider.cs - This class is also the same as above, i.e., implementation of email sending using email server as GMail.
public class GmailProvider : IEmailService
{
public bool SendMail(EmailInfo emailInfo)
{
MailMessage mail = new MailMessage();
mail.To.Add(emailInfo.To);
mail.From = new MailAddress(emailInfo.From);
mail.Subject = emailInfo.Subject;
mail.Body = emailInfo.Body;
mail.IsBodyHtml = true;
SmtpClient smtp = new SmtpClient();
smtp.Host = "smtp.gmail.com";
smtp.Port = 587;
smtp.Credentials = new System.Net.NetworkCredential(
"YourUserName@gmail.com", "YourGmailPassword");
smtp.EnableSsl = true;
try
{
smtp.Send(mail);
return true;
}
catch (Exception ex)
{
return false;
}
}
}
Implementation of Dependency Injection
- Constructor Injection - This is the most common dependency injection. Here, Interface is injected into a dependent object.
public class EmailSender_ConstInjection
{
private IEmailService _iEmailService;
public EmailSender_ConstInjection(IEmailService _mailService)
{
this._iEmailService = _mailService;
}
public void Notification(EmailInfo ObjEmailInfo)
{
_iEmailService.SendMail(ObjEmailInfo);
}
}
- Property Injection - Property or setter injection - it is best used when dependency is optional.
public IEmailService EmailService { get; set; }
public void SendNotification()
{
if (EmailService != null)
{
EmailService.SendMail(emailInfo);
}
}
- Method Injection - We can supply dependency via a method parameter.
public void PromotionalNotification(IEmailService _emailService)
{
_emailService.SendMail(emailInfo);
} public void PromotionalNotification(IEmailService _emailService)
{
_emailService.SendMail(emailInfo);
}
Interesting Points about DI
- Reduces tight coupling - loose coupling
- Easy configuration - We can easily manages injections
- Major advantage of dependency injection is that it can make testing a lot easier