Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 835
Matt Burland Avatar asked Aug 10 '15 19:08

Matt Burland


1 Answers

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 :)

like image 129
gezzahead Avatar answered Nov 05 '22 04:11

gezzahead