繁体   English   中英

.NET 核心中的 DI 问题

[英]DI issue in .NET Core

我有一个 odata 查询生成器 class 用于构建我的 odata 字符串,该字符串根据调用它的 object 对结果进行消毒。

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 和 logger。

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 框架中,我将从 UosOdataQueryBuilder 的构造函数中删除参数并解决其中的依赖关系。 例如:

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

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

您可以为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<>));

并在您的 controller 中注入IUosOdataQueryBuilder

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

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

我同意坚持注入的评论,但您可以使用IServiceProvider检索 class 中的依赖项

例如

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM