首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何将依赖注入到Newtonsoft JsonConverter中.NET核心3.1中

如何将依赖注入到Newtonsoft JsonConverter中.NET核心3.1中
EN

Stack Overflow用户
提问于 2021-10-11 02:02:14
回答 3查看 1.7K关注 0票数 1

我无法让依赖注入为下面的Newtonsoft JsonConverter在.NET Core3.1中工作。

我只想在属性级别使用它,而不是在全局级别使用它。因此,只有当指定的属性来自某个类(Es)时,才应该执行它。

JsonConverter

代码语言:javascript
运行
复制
public class HelloWorldCustomConverter : JsonConverter<string>
{
    private readonly IMyService _myService;

    public HelloWorldCustomConverter(IMyService myService)
    {
        _myService = myService;
    }
    public override bool CanRead => false;
            
    public override string ReadJson(JsonReader reader, Type objectType, string existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, string value, JsonSerializer serializer)
    {
        // append a value using the injected service
        writer.WriteValue($"{value}-{myService.GetValue()}");
    }
}

用法:

代码语言:javascript
运行
复制
public class MyClass
{   
    public string Title {  get; set; }

    [JsonConverter(typeof(HelloWorldCustomConverter))]
    public string Details {  get; set; }
}

它是.NET Core3.1和Newtonsoft.json版本13.0.1。

我很感谢你的帮助,谢谢。

编辑1

我从StackOverflow那里查了很多答案,但到目前为止没有一个对我有用。他们中的大多数人已经过时了,或者缺少了一些东西来让它发挥作用。我已经查过的几个对我没有用的:

编辑2

我试过作为重复引用的帖子,但在我的情况下不起作用。

我试着旋转我的头和各种各样的其他选择,但没有运气。

詹姆斯(日期:2108年)提出的建议之一没有奏效。

参考文献:https://github.com/JamesNK/Newtonsoft.Json/issues/1910

你可以尝试这样的方法

代码语言:javascript
运行
复制
public class JsonOptions : IConfigureOptions<MvcJsonOptions>
{
    IHttpContextAccessor _accessor;

    public JsonOptions(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }

    public virtual void Configure(MvcJsonOptions options)
    {
        options.SerializerSettings.Converters.Add(new MyCustomConverter(_accessor));
    }
}

在你的启动中注册

代码语言:javascript
运行
复制
services.AddSingleton<IConfigureOptions<MvcJsonOptions>, JsonOptions>()

(不记得默认情况下是否注册了IHttpContextAccessor,因此您可能也需要注册)

然后,在读/写Then方法中,使用_accessor.HttpContext访问请求的上下文

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-02-22 18:05:08

下面是它对我的作用:

使用ContractResolver。(我在我的案例中使用转换器)。

自定义ContractResolver.根据需要更改逻辑.

代码语言:javascript
运行
复制
using HelloWorld.Attributes;
using HelloWorld.Helpers;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Reflection;

namespace HelloWorld.Serializers
{
    public class MyCustomContractResolver : CamelCasePropertyNamesContractResolver
    {       
        private readonly IServiceProvider _serviceProvider;
        public MyCustomContractResolver(IServiceProvider serviceProvider)
        {           
            _serviceProvider = serviceProvider;
        }
        protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
        {
            var property = base.CreateProperty(member, memberSerialization);

            // this condition is specific to my case, just to showcase how I'm accessing value from HTTP Context
            if (Attribute.IsDefined(member, typeof(MyCustomAttribute),true))
            {
                if (property.PropertyType == typeof(string))
                {
                    PropertyInfo propertyInfo = member as PropertyInfo;
                    // access required services here
                    var contextAccessor = _serviceProvider.GetRequiredService<IHttpContextAccessor>();
                    var customHelper = _serviceProvider.GetRequiredService<ICustomHelper>();
                    var attribute = (MyCustomAttribute)member.GetCustomAttribute(typeof(MyCustomAttributeAttribute));
                    property.ValueProvider = new StringValueProvider(propertyInfo, customHelper, contextAccessor, attribute);
                }
            }

            return property;
        }

        public class StringValueProvider : IValueProvider
        {
            private PropertyInfo _targetProperty;
            private readonly ICustomHelper _customHelper;
            private readonly IHttpContextAccessor _httpContextAccessor;
            private readonly MyCustomAttribute _attribute;
            public StringValueProvider(
                PropertyInfo targetProperty, 
                ICustomHelper customHelper, 
                IHttpContextAccessor httpContextAccessor,
                MyCustomAttribute attribute)
            {
                _targetProperty = targetProperty;
                _customHelper = customHelper;
                _httpContextAccessor = httpContextAccessor;
                _attribute = attribute;
            }

            // SetValue gets called by Json.Net during deserialization.
            // The value parameter has the original value read from the JSON;
            // target is the object on which to set the value.
            public void SetValue(object target, object value)
            {
                _targetProperty.SetValue(target, value);
            }

            // GetValue is called by Json.Net during serialization.
            // The target parameter has the object from which to read the value;
            // the return value is what gets written to the JSON
            public object GetValue(object target)
            {
                object value = _targetProperty.GetValue(target);
                var userId = _httpContextAccessor.HttpContext.Request.Headers["UserId"].ToString();
                return value == null ? value : _customHelper.SetGreetingsTextForUser(value.ToString(),userId, _attribute.UserRole);
            }
        }
    }
}

MvcNewtonsoftJsonOptionsWrapper与serviceProvider注入

代码语言:javascript
运行
复制
using HelloWorld.Serializers;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using System;

namespace HelloWorld.Extensions
{
    public class MvcNewtonsoftJsonOptionsWrapper : IConfigureOptions<MvcNewtonsoftJsonOptions>
    {
        IServiceProvider ServiceProvider;
        public MvcNewtonsoftJsonOptionsWrapper(IServiceProvider serviceProvider)
        {
            this.ServiceProvider = serviceProvider;
        }
        public void Configure(MvcNewtonsoftJsonOptions options)
        {
            options.SerializerSettings.ContractResolver = new MyCustomContractResolver(ServiceProvider);
        }
    }
}

ServiceCollection扩展来注册ContractResolver:

代码语言:javascript
运行
复制
public static class ServiceCollectionExtensions
{
    public static IServiceCollection MyCustomContractResolver(this IServiceCollection services)
    {
        services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
        services.AddTransient<IConfigureOptions<MvcNewtonsoftJsonOptions>, MvcNewtonsoftJsonOptionsWrapper>();
        return services;
    }
}

在Startup.cs文件中,在DI中注册ContractResolver:

代码语言:javascript
运行
复制
public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddAppendSasTokenContractResolver();
    ...
}

就这样。如果这对你有用,请告诉我!

票数 1
EN

Stack Overflow用户

发布于 2022-02-22 16:43:06

托马斯的博客文章中的评论判断,您已经尝试过他的方法。不管你是否成功地让它发挥作用,当我试图实现Thomas的hack时,我会发布我遇到的问题的解决方案--也许这会对其他人有所帮助。

在我的设置中,定制的JsonConverter实际上不是由MVC框架直接实例化的,而是通过Newtonsoft的JToken.ToObject()间接地进行实例化,后者创建了一个带有默认JsonSerializerSettingsJsonSerializer。在ToObject()的调用链中,使用这些默认设置实例化了我的自定义JsonConverter

为了使的hack工作,我需要将IConfigureOptions<MvcNewtonsoftJsonOptions>.Configure()'的实现更改为:

代码语言:javascript
运行
复制
public void Configure(MvcNewtonsoftJsonOptions options)
{
    JsonConvert.DefaultSettings = () =>
    {
        var settings = new JsonSerializerSettings();
        settings.Converters.Add(new ServiceProviderDummyConverter(_httpContextAccessor, _serviceProvider));
        return settings;
    };
}
票数 0
EN

Stack Overflow用户

发布于 2021-10-12 16:36:50

IMHO --你想要达到的目标有很大的问题。序列化控制器方法的结果不应该包含任何逻辑。

更重要的是,您的api应该允许内容协商,其中Accept: application/json为您提供一个json字符串,而Accept: application/xml为您提供一个xml。

相反,您应该利用依赖注入,将MyService注入到其他服务中,并在那里调用myResult.whatever = myService.GetValue()

票数 -4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69520303

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档