Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Mastering Ninject for Dependency Injection

You're reading from   Mastering Ninject for Dependency Injection For .NET developers and architects, this is the ultimate guide to the principles of Dependency Injection and how to use the automating features of Ninject in the most effective way. Packed with examples, diagrams, and illustrations.

Arrow left icon
Product type Paperback
Published in Sep 2013
Publisher Packt
ISBN-13 9781782166207
Length 142 pages
Edition 1st Edition
Tools
Arrow right icon
Author (1):
Arrow left icon
Daniel Baharestani Daniel Baharestani
Author Profile Icon Daniel Baharestani
Daniel Baharestani
Arrow right icon
View More author details
Toc

My First DI Application


We start our example with a service class in which the concerns are not separated. Then we will improve maintainability step-by-step, by first separating concerns and then programming to interface in order to make our modules loosely coupled. At the final point, we will have our first DI application. The source code for all the examples of this book is available for download on the publisher's website.

The main responsibility of this service is to send an e-mail using the information provided. In order to make the example simple and clear, client initialization is omitted.

class MailService
{
  public void SendEmail(string address, string subject, string body)
  {
    var mail = new MailMessage();
    mail.To.Add(address);
    mail.Subject = subject;
    mail.Body = body;
    var client = new SmtpClient();
    // Setup client with smtp server address and port here
    client.Send(mail);
  }
} 

Then, we add some logging to it, so that we know what is going on in our service:

class MailService
{
  public void SendMail(string address, string subject, string body)
  {
    Console.WriteLine("Creating mail message...");
    var mail = new MailMessage();
    mail.To.Add(address);
    mail.Subject = subject;
    mail.Body = body;
    var client = new SmtpClient();
    // Setup client with smtp server address and port here
    Console.WriteLine("Sending message...");
    client.Send(mail);
    Console.WriteLine("Message sent successfully.");
  }
}

After a little while, we find it useful to add time to our logs. In this example, sending the mail message and logging functionality are two different concerns which are addressed in a single class, and it is not possible to change the logging mechanism without touching the MailService class. Therefore, in order to add time to our logs, we have to change the MailService class. So, let's re-factor this class and separate the concern of logging from sending a mail prior to adding the time functionality:

class MailService
{
  private ConsoleLogger logger;
  public MailService()
  {
    logger = new ConsoleLogger();
  }

  public void SendMail(string address, string subject, string body)
  {
    logger.Log("Creating mail message...");
    var mail = new MailMessage();
    mail.To.Add(address);
    mail.Subject = subject;
    mail.Body = body;
    var client = new SmtpClient();
    // Setup client with smtp server address and port here
    logger.Log("Sending message...");
    client.Send(mail);
    logger.Log("Message sent successfully.");
  }
}

The ConsoleLogger class is only responsible for the logging mechanism, and this concern is removed from MailService. Now, it is possible to modify the logging mechanism without affecting MailService:

class ConsoleLogger
{
  public void Log(string message)
  {
    Console.WriteLine("{0}: {1}", DateTime.Now, message);
  }
}

Now, we need to write our logs in Windows Event Log rather than showing them in console. Looks like we need an EventLogger class as well:

class EventLogger
{
  public void Log(string message)
  {
    EventLog.WriteEntry("MailService", message);
  }
}

Although the concern of sending mail and logging are now separated in two different classes, MailService is still tightly coupled to the ConsoleLogger class, and it is not possible to replace its logger without modifying it. We are just one step away from breaking the tight coupling between the MailService and Logger classes. We should now introduce the dependencies as interfaces rather than concrete classes:

interface ILogger
{
  void Log(string message);
}

Both the ConsoleLogger and EventLogger classes should implement this interface:

class ConsoleLogger:ILogger
{
  public void Log(string message)
  {
    Console.WriteLine("{0}: {1}", DateTime.Now, message);
  }
}
class EventLogger:ILogger
{
  public void Log(string message)
  {
    EventLog.WriteEntry("MailService", message);
  }
}

Now, it is time to remove the references to the concrete ConsoleLogger class and address ILogger instead:

private ILogger logger;
public MailService()
{
  logger = new ILogger();
}

But the previous code won't compile because it doesn't make sense to instantiate an interface. We should introduce this dependency as a constructor parameter and have the concrete object injected into it by a third party:

public MailService(ILogger logger)
{
  this.logger = logger;
}

At this point, our classes are loosely coupled and we can change the loggers freely without affecting the MailService class. Using DI, we have also separated the concern of creating a new instance of the logger class, which includes the concern of deciding what concrete logger to use from the main responsibility of MailService, which is sending an e-mail:

internal class Program
{
  private static void Main(string[] args)
  {
    var mailService = new MailService(new EventLogger());
    mailService.SendMail("someone@somewhere.com", "My first DI App", "Hello World!");
  }
}

The main method of this application is where we decide what concrete objects to inject in our dependent classes. This (preferably) unique location in the application where modules are composed together is named Composition Root by Mark Seemann. For more information on DI, Dependency Injection in .NET, by Mark Seemann is recommended.

lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime
Banner background image