如何使用dotnet core 2 api选项进行依赖注入?

时间:2018-03-19 12:15:00

标签: asp.net-core json.net .net-core

我在启动配置服务中有以下代码:

 services.AddMvc(options => options.RespectBrowserAcceptHeader = true)
            .AddXmlDataContractSerializerFormatters()
            .AddXmlSerializerFormatters()
            .AddJsonOptions(o =>
            {
                o.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
            });

以下型号:

public interface ITestInterface
{
    string Hello { get; set; }
}

public class TestInput
{
     public string IWork { get; set; }
     public ITestInterface IDontWork { get; set; }
}

关于我的控制器操作:

public async Task<IActionResult> Update([FromBody]TestInput testInput)
{

}

如果我发送以下JSON:

{
    "IWork": "I do work",
    "IDontWork": { "Hello": "hi hi" }
}

我正确地填充了IWork,但IDontWork却没有。但是,我的界面被注册为临时服务...我是否需要在JSON选项中设置其他内容或使用我自己的合同解析器?

1 个答案:

答案 0 :(得分:1)

  

但是,我的界面已注册为临时服务......

是的,但JSON.Net未与ASP.Net核心依赖注入集成。因此,反序列化器不知道如何创建ITestInterface的实例。

  

我是否需要在JSON选项中设置其他内容或使用我自己的合约解析器。

是的,您应该付出一些努力来覆盖这种情况,而自定义合同解析器似乎是最合适的方式。您应采取的步骤如下:

  1. 定义自定义合约解析程序。 您可以将其基于JSON.Net使用的DefaultContractResolver。您应该将IServiceProvider的实例传递给此解析器,该解析器将用于实例化已注册的类型。

  2. Startup.ConfigureServices()中注册JSON.Net反序列化期间合同解析程序可以使用的所有类型。

  3. 创建自定义合约解析程序的实例并将其设置为SerializerSettings.ContractResolver。在Startup.ConfigureServices()中,您还无权访问IServiceProvider,因为它尚未创建(因为服务仍在注册)。但是,您可以通过调用services.BuildServiceProvider()自行创建它。但请确保在此次通话前已注册所有必需的服务。

  4. 以下是执行所有描述步骤的示例:

    DependencyInjectionContractResolver类:

    public class DependencyInjectionContractResolver : DefaultContractResolver
    {
        private readonly IServiceProvider serviceProvider;
        private readonly List<Type> registeredTypes;
    
        public DependencyInjectionContractResolver(IServiceProvider serviceProvider, IEnumerable<Type> registeredTypes)
        {
            this.serviceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
            this.registeredTypes = registeredTypes?.ToList() ?? throw new ArgumentNullException(nameof(registeredTypes));
        }
    
        protected override JsonContract CreateContract(Type objectType)
        {
            JsonContract contract = base.CreateContract(objectType);
    
            if (registeredTypes.Contains(objectType))
            {
                contract.DefaultCreator = () => serviceProvider.GetService(objectType);
            }
    
            return contract;
        }
    }
    

    Startup.ConfigureServices(IServiceCollection services)方法:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddTransient<ITestInterface, TestClass>();
        //  Register all other services here
        //  ...
    
        services.AddMvc(options => options.RespectBrowserAcceptHeader = true)
            .AddXmlDataContractSerializerFormatters()
            .AddXmlSerializerFormatters()
            .AddJsonOptions(o =>
            {
                o.SerializerSettings.ContractResolver = new DependencyInjectionContractResolver(services.BuildServiceProvider(),
                    new[] { typeof(ITestInterface) } );
    
                o.SerializerSettings.Formatting = Newtonsoft.Json.Formatting.Indented;
            });
    }