Dependency injection
Introduction to official website
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2
Scrutor
- Open source address https://github.com/khellang/Scrutor
- Reference document https://www.cnblogs.com/catcher1994/p/10316928.html
Manual management of dependency injection is too cumbersome. When there are multiple repositories and services that cannot be injected uniformly, Scrutor can help us simplify the DI registration of ASP.NET Core.
In ConfigServices, we need to inject warehousing, services and other interfaces and implementations in this way. When there are multiple warehousing, it is too cumbersome.
services.AddTransient<IUserRepository, UserRepository>(); services.AddTransient<IUserService, UserService>(); services.AddTransient<ICurrentUser, CurrentUser>();
Servce suffix service injection DI
When we have services with multiple Service suffixes, we can use the following methods to scan the services and leave only the classes ending with Service, register their types to provide all public interface generation services, and their life cycle is Transient,
services.Scan(scan => scan //Load the assembly of Startup .FromAssemblyOf<Startup>() // Indicates to register those classes. The above code also filters, leaving only classes ending in Service .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service", StringComparison.OrdinalIgnoreCase))) //Indicates that the type is registered to provide all its public interfaces as services .AsImplementedInterfaces() //Indicates that the registered life cycle is Transient .WithTransientLifetime() );
ITransientDependency
Create a new empty interface, and when other classes inherit this interface, inject it into DI uniformly to achieve Transient life cycle.
namespace LinCms.Zero.Dependency { public interface ITransientDependency { } }
Interface
public interface ICurrentUser { int? Id { get; } int? GroupId { get; } bool? IsAdmin { get; } }
Simulation Implementation
public class CurrentUser : ICurrentUser, ITransientDependency { public int? Id => 1; public int? GroupId => 2; public bool? IsAdmin => true; }
Scan all implementations that inherit ITransientDependency.
services.Scan(scan => scan // We start out with all types in the assembly of ITransientService .FromAssemblyOf<ITransientDependency>() // AddClasses starts out with all public, non-abstract types in this assembly. // These types are then filtered by the delegate passed to the method. // In this case, we filter out only the classes that are assignable to ITransientService. .AddClasses(classes => classes.AssignableTo<ITransientDependency>()) // We then specify what type we want to register these classes as. // In this case, we want to register the types as all of its implemented interfaces. // So if a type implements 3 interfaces; A, B, C, we'd end up with three separate registrations. .AsImplementedInterfaces() // And lastly, we specify the lifetime of these registrations. .WithTransientLifetime() );
How to use
Use this interface in other classes
[ApiController] [Route("cms/user")] public class UserController : ControllerBase { private readonly ICurrentUser _currentUser; public UserController(ICurrentUser currentUser) { _currentUser = currentUser; } [HttpGet] public int GetUser() { return _currentUser.Id; } }
Unified injection
Of course, we can unify the injection rather than write the second servics.Scan
services.Scan(scan => scan .FromAssemblyOf<Startup>() .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service",StringComparison.OrdinalIgnoreCase))) .AsImplementedInterfaces() .WithTransientLifetime() .FromAssemblyOf<ITransientDependency>() .AddClasses(classes => classes.AssignableTo<ITransientDependency>()) .AsImplementedInterfaces() .WithTransientLifetime() );