ASP.NET Core Basic Use dependency injection

ASP.NET Core Dependency Injection

ASP.NET Core layer provides support for the framework dependency injection. That is, if you do not understand dependency injection, it will be difficult to adapt to ASP.NET Core development model. This article introduces the basic concepts of dependency injection, combined with code that demonstrates how to use dependency injection in ASP.NET Core in.

What is dependency injection?

Baidu Encyclopedia for dependency injection introduction:

Inversion of control (Inversion of Control, abbreviated as the IoC), one design principles of object oriented programming, can be used to reduce the degree of coupling between the computer code. The most common method is called dependency injection (Dependency Injection, referred to as DI), there is a way called "dependent lookup" (Dependency Lookup). By inversion of control, when the object was created by an outside entity for all objects within a regulatory system on which it depends object passed to it. It can be said, it is injected into the subject dependency.

As can be seen from the description Encyclopedia, inversion control and dependency injection is one thing, implantation is dependent on the design of a new model, the related art by the correct use of dependency injection, the system can reduce the degree of coupling, increases system scalability sex.

Let's look at an example:

public interface IInterfaceA
{ }

public interface IInterfaceB
{ }

public class ClassA : IInterfaceA
{
    private IInterfaceB B { get; set; }

    public ClassA(IInterfaceB b)
    {
        this.B = b;
    }
}

public class ClassB : IInterfaceB
{ }

This time, if we want to get IInterfaceA instance, if do not use dependency injection, our approach is usually like this:

IInterfaceB b = new ClassB();
IInterfaceA a = new ClassA(b);

This time control IInterfaceA in instantiated when he died has been limited, there is no imagination, is an instance of ClassA, and we have to manually initialize IInterfaceB, the same control over B is also limited died. There is no such code design, but also extremely conducive to expansion.

If dependency injection, we look at the code:

var a = container.GetService<IInterfaceA>();

This time control interfaces A and B are controlled by the container, we can inject different interfaces implemented by the vessel to expand the flexibility of the system, since the control to the IoC container, we can also configure flexible way to control the lifetime of the object, which is also manually create an object can not be achieved.

Inversion of Control diagram below (picture from official website):
image

The dependency injection ASP.NET Core

The above describes the basic concepts of dependency injection, then ASP.NET Core, we do how to use dependency injection? In ASP.NET Core has built a dependency injection container, we can directly use.

Add Startup.ConfigureServices in services and realize we have to register, can be added when the corresponding configuration life cycle services, then you can use where needed PageModel, Controller, Views and so on.

The following example shows how to register service code from the official website. We must first define a service interface, and implements this interface:

public interface IMyDependency
{
    Task WriteMessage(string message);
}

public class MyDependency : IMyDependency
{
    private readonly ILogger<MyDependency> _logger;

    public MyDependency(ILogger<MyDependency> logger)
    {
        _logger = logger;
    }

    public Task WriteMessage(string message)
    {
        _logger.LogInformation(
            "MyDependency.WriteMessage called. Message: {MESSAGE}", 
            message);

        return Task.FromResult(0);
    }
}

Then we conduct service registration:

public void ConfigureServices(IServiceCollection services)
{
    services.AddScoped<IMyDependency, MyDependency>();
    services.AddMvc();
}

Here we add a registered IMyDependency, but also added the use of the service Mvc require registration. There are two issues should be noted:

  • AddScoped is to add a service registry, Scoped life cycle of the service, expressed in terms of the role of creating the service, if the scope of the service to be used multiple times, only to create an object. For example, each HTTP request is a scope, then the request process, the container will create an object. Corresponding with Scoped there are other life cycle, we will serve the life cycle are listed below:

    • Transient: instantaneous service, represent each time a new object is created
    • Scoped: the scope of services, represent only one object is created for each request. It should be special instructions, if you are a service middleware, not subject to this constraint because the middleware is mandatory singleton. If you are using Scoped services middleware, you need to be injected into the service parameters or InvokeAsync Invoke method, where you can reference ASP.NET Core middleware basic usage
    • Singleton: Singleton service, indicates that each application domain will create a strength.
  • Based on the agreement, ASP.NET Core recommend we use similar Add{SERVICE_NAME}ways to add registration services, such as services.AddMvc (), this approach can be achieved by extending the method, as follows:
namespace Microsoft.Extensions.DependencyInjection
{
    public static partial class MyDependencyExtensions
    {
        public static IServiceCollection AddMyDependency(this IServiceCollection services)
        {
            return services.AddScoped<IMyDependency, MyDependency>();
        }
    }
}

Use dependency injection

After understanding the basic usage of dependency injection, we now look at how the service is injected into the Controller, Views in.

Services injected in the controller

The most common usage is to use constructor injection manner, a service will be injected into the controller, as follows:

public class DefaultController : Controller
{
    private readonly ILogger<DefaultController> logger;

    public DefaultController(ILogger<DefaultController> logger)
    {
        this.logger = logger;
    }
}

Constructor injection is the most commonly used injection method, this approach requires providing dependence public constructors, and the item dependent addicts passed by way of the constructor, assignment complete dependencies.

In addition, also by way of injection parameters, the dependency is injected into the Action, where used to FromServices characteristics:

public IActionResult Index([FromServices]ILogger<DefaultController> logger)
{
    throw new NotImplementedException();
}

ASP.NET Core provides this support, but the authors do not recommend this operation

Injection service in the view

ASP.NET Core support dependency injected into view, as follows:

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
   string myValue = Configuration["root:parent:child"];
   ...
}

The above code shows the service IConfiguration injected into view, in order to achieve read function arranged in the view.

Sometimes the service is injected into the view would be useful (eg localization), but the author is not very recommended, because doing so is likely to cause border view and controller are not clear.

Inject services in PageModel

Injection services in PageModel way, the way of injecting and services in the Controller like:

public class IndexModel : PageModel
{
    private readonly IMyDependency _myDependency;

    public IndexModel(IMyDependency myDependency)
    {
        _myDependency = myDependency;
    }
}

Access to services in the main method

public static void Main(string[] args)
{
    var host = CreateWebHostBuilder(args).Build();

    using (var serviceScope = host.Services.CreateScope())
    {
        var services = serviceScope.ServiceProvider;

        try
        {
            var serviceContext = services.GetRequiredService<MyScopedService>();
            // Use the context here
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred.");
        }
    }

    host.Run();
}

Access to services in the HttpContext.RequestServices

This approach is not conducive to the test is not recommended for such use.

Although the priority would be to get the service through constructor injection, but sometimes difficult to avoid the need for manual access to services, we should get from HttpContext.RequestServices when using hand-in access to services.

Using third-party dependency injection framework

Limited ASP.NET Core built-in function dependency injection framework, when we want to use the characteristics of third-party framework, we can replace the default dependency injection framework.

ASP.NET Core injection characteristics of the built-in frame dependency is not included:

  • Properties injection
  • Based on the injection name
  • Child container
  • Custom Lifecycle Management
  • Func for lazy initialization of objects stand by

If we use these features, we can use third-party frameworks. In this paper, an official document Autofac framework.

  • First add Autofac, Autofac.Extensions.DependencyInjection references
  • Startup.ConfigureServices disposed in the container, and returns IServiceProvider. When using a third-party container, it must return IServiceProvider.
public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    // Add other framework services

    // Add Autofac
    var containerBuilder = new ContainerBuilder();
    containerBuilder.RegisterModule<DefaultModule>();
    containerBuilder.Populate(services);
    var container = containerBuilder.Build();
    return new AutofacServiceProvider(container);
}
  • Configuration Module Autofac, used registration services
public class DefaultModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterType<CharacterRepository>().As<ICharacterRepository>();
    }
}

Reference material

Guess you like

Origin www.cnblogs.com/youring2/p/10926590.html