簡體   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