8

我是南希的菜鸟。我一直将它用作生成 REST API 的框架。我熟悉 Json.NET,所以我一直在玩这个Nancy.Serialization.JsonNet包。

JsonNetSerializer我的目标:自定义and的行为(即更改设置)JsonNetBodyDeserializer

具体来说,我想合并以下设置...

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

我想使用内置的 TinyIoC 容器来执行此自定义,以避免继承链并限制由Nancy.Serialization.JsonNet包中的任何更改引起的潜在问题。

注意:作为一种临时解决方法,我利用继承来创建CustomJsonNetSerializerCustomJsonNetBodyDeserializer.

我已经尝试了几种方法来合并这种配置,至少对于JsonNetSerializer. 我还没有尝试JsonNetBodyDeserializer使用 TinyIoC 进行配置。我想它会以类似的方式完成。我尝试过的所有工作都在我的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 ) ) );
}

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

潜在问题:我注意到构造函数被调用了两次。我没想到会有这种行为。

第一次一切都恰到好处 - 我的自定义已正确添加和注册。但是,第二次发生并且类型被重新注册,没有设置自定义。重新注册似乎取代了失去我的设置自定义的原始注册。

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

似乎我要么需要告诉南希不要做某事,要么我需要加入链条的后面部分。

任何帮助,将不胜感激。

4

1 回答 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; }
}

问: 这种方法与创建继承自 JsonNetSerializer 的 CustomJsonNetSerializer 然后在 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 的任何地方的实现设置保持一致。

问: 我能否从您概述的方法中正确推断出我不再需要在我的 CustomNancyBootstrapper 的 ConfigureApplicationContainer 覆盖中显式注册 CustomJsonSerializer?

A: 我做的注册方法只是一个更干净的注册依赖的抽象,而不是做一个巨大的Bootstrapper,你可以创建一些更小的特定类。

是的,使用我的方法意味着您不需要在引导程序中注册。

于 2014-07-22T07:24:38.433 回答