Showing posts with label Dependency Injection. Show all posts
Showing posts with label Dependency Injection. Show all posts

Tuesday, 14 March 2023

.NET Core Built In Dependency Injection

.NET has built in tool for dependency injection. 'Microsoft.Extensions.DependencyInjection' library has common features needed for IoC that is usually good enough for most applications. However if you need more advanced features, consider using other DI tools.

To use, first install 'Microsoft.Extensions.DependencyInjection' package in our project.

To register the interfaces and objects, use either AddTransient(), AddScoped() or AddSingleton() methods. Their lifetimes are:
  • AddTransient - new instance is created each time requested
  • AddScoped - new instance is created per client request/session
  • AddSingleton - created once only through application life, subsequent requests will access the same instance
To understand the lifetimes better, please check this article .

Then we use GetService() method to get an instance.

An example of how to use the tool in a unit test:
[TestClass]
public class ExampleTest
{
    private readonly IStudentRepository studentRepository;

    public ExampleTest()
    {
        var services = new ServiceCollection();
        services.AddTransient<IStudentRepository, StudentRepository>();

        var serviceProvider = services.BuildServiceProvider();

        studentRepository = serviceProvider.GetService<IStudentRepository>();
		
		. . .
    }
}

To use it in different projects, we can create an extension method of IServiceCollection in the particular project. For example, in service project:
public static class IServiceCollectionExtension
{
	public static IServiceCollection AddServicesConfiguration(this IServiceCollection services)
	{
		services.AddTransient<IStudentService, StudentService>();
		return services;
	}
}
and in repository project:
public static class IServiceCollectionExtension
{
	public static IServiceCollection AddRepositoriesConfiguration(this IServiceCollection services)
	{
		services.AddTransient<IStudentRepository, StudentRepository>();
		return services;
	}
}
Some people like to do this approach but then a project that wants to use the extension method(s) needs to directly reference the other project(s). For example; a web project will need to reference service and repository projects.

Personally, I prefer to create a bootstrap project that contains all DI mappings and has references to all projects needed. Then a project just need to reference the bootstrap project.

In this example, the WebAPI project just need to reference Bootstrap project, not Service and Repository projects.

All DI configurations are in one place:
public static class BootstrapConfig
{
	public static IServiceCollection RegisterRepositories(this IServiceCollection services)
	{
		services.AddTransient<IStudentRepository, StudentRepository>();
		return services;
	}

	public static IServiceCollection RegisterServices(this IServiceCollection services)
	{
		services.AddTransient<IStudentService, StudentService>();
		return services;
	}
}

Thursday, 31 January 2013

Basic Usage of Unity for Dependency Injection in MVC 4 Project

First, we need to install Unity Application Block library. If you use NuGet:
PM> install-package Unity.Mvc3
Yes, that is the correct version even for MVC 4 (at least at the time of writing).

Bootstrapper.cs file will be created in the project.

Next, inside Applicaton_Start() in Global.asax.cs, put this code:
Bootstrapper.Initialise();

Then register our components inside BuildUnityContainer() method in Bootstrapper.cs. For example:
        . . .
        container.RegisterType<IColourRepository, ColourRepository>();
        container.RegisterType<IInvoiceRepository, InvoiceRepository>();
        . . .

Calling container.RegisterControllers() in order to register controllers is no longer required in recent version.

Thursday, 21 June 2012

Mocking AutoMapper in Unit Testing

This post will show how to mock AutoMapper with Moq in unit testing. Unit testing that has dependency to AutoMapper would require all of the mapping configurations be specified and run first before the actual mapping takes place (Mapper.Map(...) is called). These configurations would be burdensome and should not be included in unit testing. A unit test for a feature should only test that particular feature the developer has written. It should not test other services or functionalities. This is where the concept of mocking come up.

To be able to mock AutoMapper, we can use Dependency Injection to inject a mapper interface to the constructor of the calling code's class rather than using AutoMapper directly. Below is an example of such interface:
public interface IMappingService
{
    TDest Map<TSrc, TDest>(TSrc source) where TDest : class;
}

Then create an implementation class for the interface. Note on line 5 that for this class we specify AutoMapper directly.
public class MappingService : IMappingService
{
    public TDest Map<TSrc, TDest>(TSrc source) where TDest : class
    {
        return AutoMapper.Mapper.Map<TSrc, TDest>(source);
    }
}

Next, bind the interface with the concrete class. Below is an example of how to do it with Ninject:
kernel.Bind<IMappingService>().To<MappingService>();

Then whenever we want to do mapping, we call the interface's Map method instead of using the AutoMapper's Mapper.Map() method.
public ViewResult List()
{
    IEnumerable<Stuff> stuffs = stuffRepository.All;

    List<StuffViewModel> model = mappingService.Map<IEnumerable<Stuff>, List<StuffViewModel>>(stuffs);

    return View("List", model);
}
Please remember that mapping configurations need to be specified first before we could do any mapping. You can see this post to see how to set up the configurations.

Now we can mock the mapper in our unit test. In the example below I use xUnit testing framework. As you can see; first we create a mock instance from the interface, setup what the Map method will return and then pass the mock object to the class constructor of the feature to be tested (line 6, 25 and 28).
[Fact]
public void ListPageReturnsStuffViewModels()
{
    // Arrange
    Mock<IStuffRepository> stuffRepository = new Mock<IStuffRepository>();
    Mock<IMappingService> mappingService = new Mock<IMappingService>();

    List<Stuff> stuffs = new List<Stuff>();
    stuffRepository.Setup(r => r.All).Returns(stuffs.AsQueryable());

    var viewModelStuffs = new List<StuffViewModel> {
        new StuffViewModel { StuffID = 1/*,
                                Name= "Bip",
                                Description= "Colourful baby bip",
                                DateAdded = DateTime.Now,
                                UserID = 1 */
        },
        new StuffViewModel { StuffID = 2/*,
                                Name= "Socks",
                                Description= "Winter socks with animal figures",
                                DateAdded = DateTime.Now,
                                UserID = 1 */
        }
    };
    mappingService.Setup(m => m.Map<IEnumerable<Stuff>, List<StuffViewModel>>(It.IsAny<IEnumerable<Stuff>>()))
                    .Returns(viewModelStuffs);

    var controller = new StuffsController(stuffRepository.Object, mappingService.Object);


    // Act
    var result = controller.List() as ViewResult;
    //var model = result.ViewData.Model as List<StuffViewModel>;


    // Assert
    var model = Assert.IsType<List<StuffViewModel>>(result.ViewData.Model);
    Assert.Equal(2, model.Count);                
}

Tuesday, 18 October 2011

Dependency Injection for Filters with Ninject in MVC3 - Backward Compatibility

Tools used when writing this article: MvcScaffolding ver 1.0.0, Ninject ver 2.2.1.4 and Ninject.MVC3 ver 2.2.2.0.

This post will describe the third way to implement dependency injection for filters in MVC3.

For the preferred way to implement filter on actions or controllers using 'BindFilter' method, please see my previous post. The second way is also described on my other post.

In this post, we will see how to implement DI using 'Inject' attribute. This way of implementing is only meant for backward compatibility for MVC prior to version 3. For more information you can see https://github.com/ninject/ninject.web.mvc/wiki/Dependency-injection-for-filters and https://github.com/ninject/ninject.web.mvc/wiki/Injection-of-filter-attributes.

Setting up the DI for filter using this way is simpler, however we could not have a centralized location to specify where the filter applies. The reason is that we need to put the filter attribute on every controller(s) or action(s) where we want the filter to apply. So, if the filter is applied on lots of controllers or actions they could be harder to track.

First we prepare our filter class with a public service property that will be dependency injected. This property access modifier must be 'public', otherwise the DI will not work because the DI is going to be done through property injection. Then put '[Inject]' attribute notation on the property. When this notation is used, Ninject will automatically apply the injection to the property. Next, bind the service interface with its implementation class inside 'RegisterServices' method on 'NinjectMVC3.cs' file. Finally we can put the '[filterattribute]' notation on controller(s) or action(s) where we want the filter to apply.

Below are the complete codes:

Service interface and its implementation class:
public interface IGreetingService
{
    string GetGreeting();
}

public class GreetingServiceImplThree : IGreetingService
{
    public string GetGreeting()
    {
        return "Greeting - Backward Compatibility";
    }
}

Filter class:
public class GreetingFilterBackwardCompAttribute: ActionFilterAttribute
{
    [Inject]
    public IGreetingService _service { get; set; }

    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ViewResult result = filterContext.Result as ViewResult;
        if (result != null)
        {
            result.ViewData["Greeting"] += _service.GetGreeting();
        }
    }
}

'RegisterServices' method on 'NinjectMVC3.cs':
private static void RegisterServices(IKernel kernel)
{
    . . .
    //bind the service interface with an implementation class
    kernel.Bind<IGreetingService>().To<GreetingServiceImplThree>();
    . . .
}   
Note here we just need to bind the service interface only, not the filter.

Usage:
[GreetingFilterBackwardComp]
public ViewResult Index()
{
    . . .
} 
To test, render 'ViewData["Greeting"]' somewhere on the view or shared view.

Monday, 10 October 2011

Dependency Injection for Filters with Ninject in MVC3 - Using Filter Attribute

Tools used when writing this article: MvcScaffolding ver 1.0.0, Ninject ver 2.2.1.4 and Ninject.MVC3 ver 2.2.2.0.

This post will describe the second way to implement dependency injection for filters in MVC3.

For the preferred way to implement filter on actions or controllers using 'BindFilter' method, please see my previous post.

In this post, we will see that we can also implement dependency injection with Filter Attributes. The steps to do this are almost similar to the steps to implement using the 'BindFilter' method (described on my previous post referred above). Except now a new attribute class that derived from 'FilterAttribute' needs to be created. Then we need to modify our filter binding in the 'RegisterServices' method to use extension methods such as 'WhenActionHas', 'WhenControllerHas' or 'WhenActionMethodHas' to refer to the attribute class. After that, the filter can be applied to a specific action or controller by putting '[filterattribute]' notation. We'll see this in more details below.

Based on our previous example, we need to add an attribute class that derived from 'FilterAttribute' base class. Nothing change on the main filter class (ie. GreetingFilter class). Below is the code for the attribute class:
public class GreetingFilterAttribute : FilterAttribute { }
Note that it is just an empty class without implementation.

Next, in our 'RegisterServices' method, we need to bind the filter attribute using extension methods such as 'WhenActionHas', 'WhenControllerHas' or 'WhenActionMethodHas'. For example:
kernel.BindFilter<GreetingFilter>(FilterScope.Action, 0)
.WhenActionMethodHas<GreetingFilterAttribute>();
The main difference in implementing DI this way compared to the first way that is described on my previous post is that inside this 'RegisterServices' method, we just need to tell the kernel to look for a filter attribute. The details of the location(s) where the filter applies is specified using '[filterattribute]' notation (on some controllers or actions). While on the first way, the specific location(s) where the filter applies is specified in the binding as well.

Then lastly, we put '[GreetingFilter]' notation on particular action(s) or controller(s) where we want the filter to apply.

Below are the complete codes:

Service interface and its implementation class:
public interface IGreetingService
{
    string GetGreeting();
}

public class GreetingServiceImplTwo : IGreetingService
{
    public string GetGreeting()
    {
        return "Greeting - Using Filter Attribute";
    }
}

GreetingFilter and it's attribute class:
public class GreetingFilter : IActionFilter
{
    private readonly IGreetingService _service;

    public GreetingFilter(IGreetingService greetingService)
    {
        this._service = greetingService;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //at the moment this is empty because we don't need this method
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ViewResult result = filterContext.Result as ViewResult;
        if (result != null)
        {
            result.ViewData["Greeting"] += _service.GetGreeting();
        }
    }
}

public class GreetingFilterAttribute : FilterAttribute { }

'RegisterServices' method on 'NinjectMVC3.cs':
private static void RegisterServices(IKernel kernel)
{
    . . .
    //bind the service interface with an implementation class
    kernel.Bind<IGreetingService>().To<GreetingServiceImplTwo>();

    //bind the filter attribute
    kernel.BindFilter<GreetingFilter>(FilterScope.Action, 0)
        .WhenActionMethodHas<GreetingFilterAttribute>();
    . . .
}   

Usage:
[GreetingFilter]
public ActionResult Create()
{
    . . .
} 
To test, render 'ViewData["Greeting"]' somewhere on the view or shared view.

Sunday, 2 October 2011

Dependency Injection for Filters with Ninject in MVC3

Tools used when writing this article: MvcScaffolding ver 1.0.0, Ninject ver 2.2.1.4 and Ninject.MVC3 ver 2.2.2.0.

There are three ways (as far as I know) to do dependency injection for filters in MVC3 using Ninject.

On this post, we'll see the preferred way first. The second way which uses filter attribute is described on my next post. While the third one which should only be used for backward compatibility can be seen on my other post.

First, we create a filter class that inherits from one of these four interfaces; IAuthorizationFilter, IActionFilter, IResultFilter or IExceptionFilter. Each interface requires us to implement particular methods defined for it. For example when we use IActionFilter, we need to implement OnActionExecuting and OnActionExecuted methods. For more information about this, see this MSDN article "Filtering in ASP.NET MVC".

Then bind the filter in the 'RegisterService' method inside 'NinjectMVC3.cs' file using 'BindFilter' method. Here we specify where the filter will apply (which controller or action or a combination of both). I'm assuming that you have used NuGet to implement Ninject in your project. That way, you will have 'NinjectMVC3.cs' file generated for you.

If you haven't implemented Ninject on your project, you can see my post "Building MVC Application using Dependency Injection with MVCScaffolding and Ninject" on how to install it.

Let's go through an example. In this example, we are going to implement a simple action filter that returns a greeting message through ViewData.
First, we create a simple service interface and an implementation class.
public interface IGreetingService
{
    string GetGreeting();
}

public class GreetingServiceImplOne : IGreetingService
{
    public string GetGreeting()
    {
        return "Greeting..";
    }
}

Then we create our filter class. Because it is an action filter, it will use IActionFilter to be inherited from.
public class GreetingFilter : IActionFilter
{
    private readonly IGreetingService _service;

    public GreetingFilter(IGreetingService greetingService)
    {
        this._service = greetingService;
    }

    public void OnActionExecuting(ActionExecutingContext filterContext)
    {
        //at the moment this is empty because we don't need this method
    }

    public void OnActionExecuted(ActionExecutedContext filterContext)
    {
        ViewResult result = filterContext.Result as ViewResult;
        if (result != null)
        {
            result.ViewData["Greeting"] += _service.GetGreeting();
        }
    }
}
Notice the class includes a private service member and a constructor to inject a service object to itself.

Lastly, we need to bind the filter inside 'RegisterServices' method in 'NinjectMVC3.cs' class. In this case we state that the filter would only apply to the Index action of PlayersController.
private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IGreetingService>().To<GreetingServiceImplOne>();

    //filter is applied to Index action of PlayersController
    kernel.BindFilter<GreetingFilter>(FilterScope.Action, 0)
        .When((controllerContext, actionDescriptor) =>
            actionDescriptor.ControllerDescriptor.ControllerType == typeof(PlayersController) &&
            actionDescriptor.ActionName == "Index");
            
    //this one here is similar as the one above            
    /*kernel.BindFilter<GreetingFilter>(FilterScope.Action, 0)
        .When((controllerContext, actionDescriptor) => 
            actionDescriptor.ControllerDescriptor.ControllerName == "Players" &&
            actionDescriptor.ActionName == "Index");*/

    //this is another example where the filter to be applied to all actions of MatchesController
    //kernel.BindFilter<GreetingFilter>(FilterScope.Action, 0).WhenControllerType<MatchesController>();
}        
Notice that, first we bind the service interface with its implementation class. Then we configure the filter using 'BindFilter' method to particular controller(s) or action(s). The commented codes show some more configuration examples.

To see more possible filter configuration see these official Ninject MVC documentation for filters; https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations and https://github.com/ninject/ninject.web.mvc/wiki/Conditional-bindings-for-filters

To test our work, just try to render our ViewData on some view pages. In my case I use a shared page for all of my views which is '_Layout.cshtml' (under 'Views/Shared' folder), so I just need to render the ViewData there and test the result.

Easy..

Friday, 16 September 2011

Building MVC Application using Dependency Injection with MVCScaffolding and Ninject

Tools used when writing this article: MvcScaffolding ver 1.0.0, EntityFramework ver 4.1.10331.0, Ninject ver 2.2.1.4 and Ninject.MVC3 ver 2.2.2.0.

We can build an MVC application with Dependency Injection on its controllers quickly with MVCScaffolding and Ninject extension for MVC3 framework (Ninject.MVC3). In fact, when we install Ninject.MVC3, we will get both Ninject and Ninject.MVC3 packages. We would also need Entity Framework installed in our project to complete this exercise.

To check all installed packages in the project with NuGet:
PM> Get-Package

Assuming we already have MvcScaffolding and Entity Framework installed (installing MvcScaffolding will automatically add EF to the project if it not exists yet), what's missing is Ninject.MVC3.
To install Ninject.MVC3, do this:
PM> Install-Package Ninject.MVC3
If successful, it will add two packages to the project (Ninject and Ninject.MVC3).
It will also add 'NinjectMVC3.cs' class under 'App_Start' folder.

Prepare our model class, in this case I use a model called 'Team'. Then run the scaffolder:
PM> Scaffold Controller Team -Repository
This will add a database context file (if not exist yet), a cs file 'Models\TeamRepository.cs', a controller 'Controllers\TeamsController.cs' and some CRUD views.

Here is the generated content of 'TeamRepository.cs' file (it includes 'ITeamRepository' interface and 'TeamRepository' class on the same file):
public class TeamRepository : ITeamRepository
    {
        MvcScaffoldTestContext context = new MvcScaffoldTestContext();

        public IQueryable<Team> All
        {
            get { return context.Teams; }
        }

        public IQueryable<Team> AllIncluding(params Expression<Func<Team, object>>[] includeProperties)
        {
            IQueryable<Team> query = context.Teams;
            foreach (var includeProperty in includeProperties) {
                query = query.Include(includeProperty);
            }
            return query;
        }

        public Team Find(int id)
        {
            return context.Teams.Find(id);
        }

        public void InsertOrUpdate(Team team)
        {
            if (team.TeamId == default(int)) {
                // New entity
                context.Teams.Add(team);
            } else {
                // Existing entity
                context.Entry(team).State = EntityState.Modified;
            }
        }

        public void Delete(int id)
        {
            var team = context.Teams.Find(id);
            context.Teams.Remove(team);
        }

        public void Save()
        {
            context.SaveChanges();
        }
    }

    public interface ITeamRepository
    {
        IQueryable<Team> All { get; }
        IQueryable<Team> AllIncluding(params Expression<Func<Team, object>>[] includeProperties);
        Team Find(int id);
        void InsertOrUpdate(Team team);
        void Delete(int id);
        void Save();
    }

and part of 'TeamController.cs' class:
  private readonly ITeamRepository teamRepository;

  // If you are using Dependency Injection, you can delete the following constructor
        public TeamsController() : this(new TeamRepository())
        {
        }

        public TeamsController(ITeamRepository teamRepository)
        {
   this.teamRepository = teamRepository;
        }

        . . .

Next, we need to uncomment this on 'TeamController.cs':
/*public TeamsController() : this(new TeamRepository())
{
}*/

Finally, bind our interface to the concrete class on 'NinjectMVC3.cs':
private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<ITeamRepository>().To<TeamRepository>();
}   
This means whenever our application encounters 'ITeamRepository' interface, it will refer to/use 'TeamRepository' class.

That's all that we need to do!

If you missed the last step, you will get this error: