.NET Core 中的 DI 问题

时间:2021-01-08 10:43:47

标签: c# asp.net-core dependency-injection

我有一个 odata 查询构建器类,我用它来构建我的 odata 字符串,它根据调用它的对象对结果进行消毒。

public class UosOdataQueryBuilder<T>
    {
        private readonly Dictionary<string, string> _queryOptions;
        private readonly IHttpClientFactory _clientFactory;
        private readonly ILogger _logger;

        public UosOdataQueryBuilder([FromServices] IHttpClientFactory clientFactory, [FromServices] ILogger logger)
        {
            _queryOptions = new Dictionary<string, string>();
            _clientFactory = clientFactory;
            _logger = logger;
        }

        public UosOdataQueryBuilder<T> WithFilter(string filter)
        {
            _queryOptions.Add("$filter", filter);
            return this;
        }

        public UosOdataQueryBuilder<T> Skip(int skip)
        {
            _queryOptions.Add("$skip", skip.ToString());
            return this;
        }

        public UosOdataQueryBuilder<T> Top(int top)
        {
            _queryOptions.Add("$top", top.ToString());
            return this;
        }

        public UosOdataQueryBuilder<T> WithNoInlineCount()
        {
            _queryOptions.Add("$inlinecount", "none");
            return this;
        }

        public UosOdataQueryBuilder<T> OrderBy(string orderBy)
        {
            _queryOptions.Add("$orderby", orderBy);
            return this;
        }

        public async Task<UosOdataReponse<T>> ExecuteQueryAsync(string elementName = "")
        {
            var result = new UosOdataReponse<T>();

            try
            {
                var authToken = AppSettings.PlatformBearerToken;

                var queryParameters = new List<string>();

                foreach (var option in _queryOptions)
                    queryParameters.Add($"{option.Key}={option.Value}");

                var queryParametersCombined = string.Join("&", queryParameters);

                var oDataElementName = (elementName == "") ? typeof(T).Name : elementName;

                var baseUrl = AppSettings.PlatformBaseUri;
               
                var client = _clientFactory.CreateClient("UOS");

                var request = new HttpRequestMessage(
                    HttpMethod.Get,
                    new Uri(baseUrl + $"/uos/v4/odata/{oDataElementName}" + queryParametersCombined));

                var response = await client.SendAsync(request);

                if (response.IsSuccessStatusCode)
                {
                    var data = await response.Content.ReadAsStringAsync();
                    result = JsonConvert.DeserializeObject<UosOdataReponse<T>>(data);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);

            }
            return result;
        }
    }

我已经在启动时设置了客户端

services.AddHttpClient("UOS", c =>
            {
                c.BaseAddress = new Uri(Configuration.GetValue<string>("PlatformBaseUri") + "uos/v4/");
                c.DefaultRequestHeaders.Add("Accept", "application/json");
                c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", Configuration.GetValue<string>("PlatformBearerToken"));
                //c.Timeout = new TimeSpan(0, 0, 30);
            });

当我从另一个方法创建一个新实例时,它要求我传入 clientFactory 和记录器。

protected async Task<int> GetUosOdataCount(string filter)
        {
            var result = new List<T>();
            try
            {
                var countCheck = await new UosOdataQueryBuilder<T>()
                    .WithFilter(filter)
                    .Top(1)
                    .ExecuteQueryAsync();

                return countCheck.Count;
            }
            catch (Exception ex)
            {
                //CustomLogger.LogError(GetType().FullName, "GetUosOdata", ex.Message);
            }
        }

在 .NET Framework 中,我将从 UosOdataQueryBuilder 的构造函数中删除参数并解析其中的依赖项。例如:

_uosUserAttributeRepository = GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IUosUserAttributeRepository)) as IUosUserAttributeRepository;

但我不确定如何在 .NET Core 中实现。有什么建议吗?

2 个答案:

答案 0 :(得分:1)

您可以为 UosOdataQueryBuilder<T> 创建一个接口并将其注册到 DI 中。像这样的事情:

public interface IUosOdataQueryBuilder<T>
{
    Task<T> SomeMethod();
}

public class UosOdataQueryBuilder<T> : IUosOdataQueryBuilder<T>
{
    private readonly Dictionary<string, string> _queryOptions;
    private readonly IHttpClientFactory _clientFactory;
    private readonly ILogger<UosOdataQueryBuilder<T>> _logger;

    public UosOdataQueryBuilder(IHttpClientFactory clientFactory, ILogger<UosOdataQueryBuilder<T>> logger)
    {
        _queryOptions = new Dictionary<string, string>();
        _clientFactory = clientFactory;
        _logger = logger;
    }

    public Task<T> SomeMethod()
    {
        return default;
    }
}

并在启动时在 ConfigureServices 中写入:

services.AddScoped(typeof(IUosOdataQueryBuilder<>), typeof(UosOdataQueryBuilder<>));

并在您的控制器中注入 IUosOdataQueryBuilder

    private readonly IUosOdataQueryBuilder<YourClass> _uosOdataQueryBuilder;
    public YourController( IUosOdataQueryBuilder<YourClass> uosOdataQueryBuilder)
    {
       _uosOdataQueryBuilder = uosOdataQueryBuilder;
    }

您可以将 IUosOdataQueryBuilder 注册为 Singleton,但为了防止内存泄漏,您应该在具体类中注入 IServiceScopeFactory 以在您的方法中而不是在构造函数中获取注册服务。

答案 1 :(得分:0)

我同意坚持注入的评论,但您可以使用 IServiceProvider

检索类中的依赖项

例如

MyMethod(IServiceProvider serviceProvider)
{
MyService svc = (MyService)serviceProvider.GetService(typeof(MyService));
...