Matt Burland
Matt Burland

Reputation: 45145

Is there a way to get dependency injection with a JsonConverter derived custom converter

Not quite the same as this:

How do I Inject Dependencies with Ninject, where instances are deserialised from json

Where the answer is that your data class that you deserialized shouldn't need a service anyway. Is there a way to use dependency inject with a class derived from JsonConverter? For example, if you had this:

[JsonConverter(typeof(MyCustomConverter))]
public class Foo
{
    public string SomeProp { get; set; }
}

And:

public class MyCustomConverter : JsonConverter
{
    private readonly IMyService myService;

    public MyCustomConverter(IMyService _myService)
    {
        myService = _myService;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var bar = myService.SomeFunctionThatMightEffectDeserialization();
        //...
    }
}

Is there anyway to hook into how JSON.Net instantiates MyCustomConverter to get it to let Ninject do it's thing?

EDIT This is NOT injecting a service into Foo like the suggested dupe. This is injecting only into MyCustomConverter so that it can then deserialize Foo.

Upvotes: 8

Views: 3091

Answers (1)

gezzahead
gezzahead

Reputation: 1256

It's a bit of a hack, but it's possible to do something similar by setting the ContractResolver in the JsonSerializerSettings. In this case, using Autofac:

var builder = new ContainerBuilder();
builder.RegisterInstance(myService);
var container = builder.Build();

var settings = new JsonSerializerSettings
{
    ContractResolver = new AutofacContractResolver(container),
};

and then in the converter:

var jsonContract = serializer.ContractResolver.ResolveContract(typeof(IMyService));
var service = (IMyService)jsonContract.DefaultCreator();

So you're not really injecting the service into the converter, but at least you can access it without a concrete dependency. Also you're not using the same Autofac container as your app but creating a new one. Not ideal, but it's something :)

Upvotes: 1

Related Questions