ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

.NET 手动获取注入对象

2022-07-26 15:03:20  阅读:142  来源: 互联网

标签:httpContextAccessor 手动 roadService 获取 NET public GetRequiredService 构造函数


前言

当我们使用DI方式写了很多的Service后, 可能会发现我们的有些做法并不是最优的.
获取注入的对象, 大家经常在构造函数中获取, 这样也是官方推荐的方式, 但有时不是效率最高的方法.
如果在构造函数中获取对象,那么每次对象的初始化都会把构造函数中的对象初始化一遍, 如果某个方法只用到其中一个注入对象, 那么其他的注入对象就白注入了

平时的做法

/// <summary>
/// xxx服务
/// </summary>
[Route("api/[controller]")]
[ApiController]
public class ValueController : ControllerBase
{
    private readonly ILogger<ValueController> _logger;
    private readonly IFreeSql _freeSql;
    private readonly IOptions<ValueOptions> _valueOptions;
    private readonly RoadService _roadService;

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <returns></returns>
    public RollerController(ILogger<ValueController> logger, IFreeSql freeSql, IOptions<ValueOptions> valueOptions, RoadService roadService)
    {
        _logger = logger;
        _freeSql = freeSql;
        _baiduOptions = baiduOptions;
        _roadService = roadService;
    }

    /// <summary>
    /// 获取所有项目
    /// </summary>
    /// <returns></returns>
    [HttpGet("project/all")]
    public Task<List<ProjectDto>> GetProjects() => _freeSql.Select<Project>().ToListAsync<ProjectDto>();

    /// <summary>
    /// 获取工程名下的道路
    /// </summary>
    /// <param name="projectId"></param>
    /// <returns></returns>
    [HttpGet("project/{projectId}/road")]
    public Task<List<RoadDto>> GetRoads([FromRoute] Guid projectId) => _roadService.GetRoads(projectId);
}

如上: 每个方法并不是都用到了构造函数中的服务, 所以我们这里就有性能损失, 毕竟创建对象也是有代价的, 而且还会伴有GC.

优化

为了能在个别的方法中注入对象就要用到手动获取注册对象的方式
如下:
在能直接拿到HttpContext时

    /// <summary>
    /// 处理道路信息
    /// </summary>
    /// <param name="roadId"></param>
    /// <exception cref="ArgumentNullException"></exception>
    [HttpPost("road/{roadid}/handle-road")]
    public async Task<ActionResult> HandleRoadInfo([FromRoute] Guid roadId)
    {
        var imageService = HttpContext.GetRequiredService.GetRequiredService<ImageService>();
        await imageService.HandleRoadInfo(roadId);
        return Ok();
    }

在不能直接拿到HttpContext时,需要先获取IHttpContextAccessor, 然后再获取 HttpContext上下文对象

/// <summary>
/// 图片服务
/// </summary>
public class ImageService
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    /// <summary>
    /// 构造函数
    /// </summary>
    public ImageService(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    /// <summary>
    /// 处理道路信息
    /// </summary>
    /// <param name="roadId"></param>
    /// <exception cref="ArgumentNullException"></exception>
    public async Task HandleRoadInfo(Guid roadId)
    {
        var roadService = _httpContextAccessor.HttpContext?.RequestServices.GetRequiredService<RoadService>();
        var data = await roadService.GetRoadData(roadId);
        // 省略其他
    }
}

注意这里面我们使用了GetRequiredService, 而没有使用GetService, 因为使用GetRequiredService不需要我们自己再去做空值检查, 如果为空再很快就会失败.

关于GetService 和 GetRequiredService

GetService()是IServiceProvider上的唯一方法,ISeviceProvider是ASP.NET核心DI抽象中的中央接口。第三方容器还可以实现可选接口ISupportRequiredService,该接口提供GetRequiredService()方法。当请求的类型serviceType可用时,这些方法的行为相同。如果服务不可用(即它没有注册),则GetService()返回null,而GetRequiredService()抛出一个InvalidOperationException。

GetRequiredService()相对于GetService()的主要好处是当服务不可用时,它允许第三方容器提供额外的诊断信息。因此,在使用第三方容器时最好使用GetRequiredService()。就个人而言,我会在任何地方使用它,即使我只使用内置的DI容器。

总结

将所有方法都用的service中使用构造函数注入是个优选方案, 将个别方法使用到的service使用手动获取的方式代码执行会更有效率

作者:wwmin
出处:https://www.cnblogs.com/cnwwm
联系:wwei.min@163.com 微信:w_wmin

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。如有问题或建议,请多多赐教,非常感谢。

标签:httpContextAccessor,手动,roadService,获取,NET,public,GetRequiredService,构造函数
来源: https://www.cnblogs.com/cnwwm/p/16520971.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有