使用Nancy TinyIoC配置JsonNetSerializer和JsonNetBodyDeserializer

9

我是Nancy的新手。 我一直在使用它作为框架来生成REST API。 我对Json.NET很熟悉,所以我一直在尝试使用Nancy.Serialization.JsonNet包。

我的目标:自定义JsonNetSerializerJsonNetBodyDeserializer的行为(即更改设置)。

具体来说,我想加入以下设置...

var settings = new JsonSerializerSettings { Formatting = Formatting.Indented };
settings.Converters.Add( new StringEnumConverter { AllowIntegerValues = false, CamelCaseText = true } );

我希望使用内置的TinyIoC容器进行此定制,以避免继承链并限制由于Nancy.Serialization.JsonNet包中任何更改而产生的潜在问题。

注意:为了临时解决问题,我利用了继承来创建CustomJsonNetSerializerCustomJsonNetBodyDeserializer

我尝试了几种方法来至少将此配置合并到JsonNetSerializer中。 我还没有尝试使用TinyIoC配置JsonNetBodyDeserializer。 我想它会类似地完成。 我所尝试的所有工作都在我的CustomNancyBootstrapper中(它继承了DefaultNancyBootstrapper)。

到目前为止,最成功的方法是覆盖ConfigureApplicationContainer

protected override void ConfigureApplicationContainer( TinyIoCContainer container )
{
    base.ConfigureApplicationContainer( container );

    // probably don't need both registrations, and I've tried only keeping one or the other
    var settings = new JsonSerializerSettings { Formatting = Formatting.Indented };
    settings.Converters.Add( new StringEnumConverter { AllowIntegerValues = false, CamelCaseText = true } );
    container.Register( new JsonNetSerializer( JsonSerializer.CreateDefault( settings ) ) );
    container.Register<ISerializer>( new JsonNetSerializer( JsonSerializer.CreateDefault( settings ) ) );
}

我已经追踪了代码并观察了JsonNet包中的JsonNetSerializer(JsonSerializer serializer)构造函数。

可能存在的问题:我注意到这个构造函数被调用了两次。我没有预料到这种行为。

第一次一切都很对 - 我的自定义设置已经被正确添加和注册。但是,接下来发生了第二次,类型被重新注册,而没有进行设置自定义。重新注册似乎替换了原始的注册,丢失了我的设置自定义。

第二次构造函数被调用时的调用堆栈显示,在GetEngine和GetEngineInternal期间调用了它,这似乎试图构建一个NancyEngine(我正在使用self-host包,所以这在program.cs中发生--using(var host = new NancyHost(uri)))。

似乎我需要告诉Nancy不要做某些事情,或者我需要钩入到链中的后面部分。

任何帮助将不胜感激。

1个回答

16

通常在Nancy中解决这个问题的方法是实现自己的JSON序列化程序,就像这样:

public sealed class CustomJsonSerializer : JsonSerializer
{
    public CustomJsonSerializer()
    {
        ContractResolver = new CamelCasePropertyNamesContractResolver();
        Converters.Add(new StringEnumConverter
        {
            AllowIntegerValues = false, 
            CamelCaseText = true
        });
        Formatting = Formatting.Indented;
    }
}

您可以在此覆盖所有设置。

然后,您可以通过使用IRegistrations进行注册。

public class JsonRegistration : IRegistrations
{
    public IEnumerable<TypeRegistration> TypeRegistrations
    {
        get
        {
            yield return new TypeRegistration(typeof(JsonSerializer), typeof(CustomJsonSerializer));
        }
    }

    public IEnumerable<CollectionTypeRegistration> CollectionTypeRegistrations { get; protected set; }
    public IEnumerable<InstanceRegistration> InstanceRegistrations { get; protected set; }
}

Q: 这种方法与创建CustomJsonNetSerializer并继承JsonNetSerializer,然后在ConfigureApplicationContainer注册它的方法有何不同?(container.Register(typeof(JsonNetSerializer), typeof(CustomJsonNetSerializer)))?

A: JsonSerializer是Nancy中json.net的实现,这是我们在github上自述文件中推荐的方法:

https://github.com/NancyFx/Nancy.Serialization.JsonNet#customization

你提到的类是将对象序列化为JSON,还有另一个处理反序列化的类,两者都内部使用JsonSerializer实现:

https://github.com/NancyFx/Nancy.Serialization.JsonNet/blob/master/src/Nancy.Serialization.JsonNet/JsonNetSerializer.cs#L10

使用这种方法可以使JsonSerializer在任何地方被调用时保持一致的设置。

Q: 我能否正确地推断出,按照您所描述的方法,我不再需要在CustomNancyBootstrapper中显式注册CustomJsonSerializer?

A: 我所做的注册方法只是一种更清晰的抽象方式来注册依赖项,而不是创建一个庞大的Bootstrapper,你可以创建几个更小的特定类。

是的,使用我的方法意味着你不需要在bootstrapper中进行注册。


有趣!从我的追踪来看,CollectionTypeRegistrations 是我失去自定义的地方。在尝试这种方法之前,有两个问题。第一,这种方法与创建继承自 JsonNetSerializer 的 CustomJsonNetSerializer 并在 ConfigureApplicationContainer 中注册它(container.Register(typeof(JsonNetSerializer), typeof(CustomJsonNetSerializer))有何不同?第二个问题是,我能否从你概述的方法中正确推断出,在我的 CustomNancyBootstrapper 中不再需要显式注册 CustomJsonSerializer 在 ConfigureApplicationContainer 覆盖中? - Rob
在答案中回答了你的问题 :) - Phill
似乎不再起作用了。在注册后,自定义JSON序列化程序的构造函数从未被调用。 Nancy就是这样一个黑匣子... - Sergey Akopov
1
@SergeyAkopov 听起来你在配置完所有内容后调用了基类,因此注册被覆盖了。基本上是用户自己的问题。 - Phill
@SergeyAkopov,很高兴你解决了这个问题。我会把它加入我的任务清单中,以便制作更清晰的文档。只需要先完成Marten文档。 :) - Phill
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接