Am using a custom JsonConverter to convert my JSON object. This is achieved via the JsonConverter attribute to the IQuery object below
[JsonConverter(typeof(CustomConverter<IQuery>))]
public interface IQuery
{
}
The custom generic class is below (some bits removed for brevity)
public class CustomConverter<T> : JsonConverter
{
// This should be created via AutoFac
public ICustomObjectCreator<T> ObjectCreator { get; set; }
// This default constructr always gets called
public CustomConverter() {}
// I want to call this constructor
[JsonConstructor]
public CustomConverter(ICustomObjectCreator<T> objectCreator)
{
Context = context;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
// Load JObject from stream
var jObject = JObject.Load(reader);
// Create target object based on JObject
var target = Create(objectType, jObject);
// Populate the object properties
serializer.Populate(jObject.CreateReader(), target);
return target;
}
protected T Create(Type objectType, JObject jObject)
{
var type = jObject.GetValue("type", StringComparison.OrdinalIgnoreCase)?.Value<string>();
return ObjectCreator.Create(type);
}
}
The ICustomObjectConverter interface is simple
public interface ICustomObjectCreator<out T>
{
T Create(string type);
}
and one of its implementation
public class QueryObjectCreator : ICustomObjectCreator<IQuery>
{
public IQuery Create(string type)
{
// ... some logic to create a concrete object
return (IQuery)concreteObject;
}
}
Finally, Autofac is wired to honor the above
builder.RegisterType<QueryObjectCreator>()
.As<ICustomObjectCreator<IQuery>>()
.InstancePerLifetimeScope();
Problems:
- When CustomJsonConverter is called, only its default constructor is called. The JsonConstructor is NEVER called.
- If I remove the default constructor, then the whole JsonConverter is NEVER called!
I have an inklinkg that AutoFac is never being called when JsonConverter is being invoked. I even tried property injection to construct QueryObjectConstruct explicitly, but even that is never called. How can I make it work so that my QueryObjectCretor is injected via DI?
I found this article about Dependency Injection and JSON.net deserialization. However, that is for manual resolve using DeserializeObject<>() call, how can I, if it works, make it work with JsonConverter attribute?
Thanks
You could do the following steps to achieve your goal:
ICustomObjectCreator
interface, to make creating objects more convenient.ObjectCreatorBase<T>
base class which calls your genericCreate
method.JsonConvert
.AutofacContractResolver
asContractResolver
.See the following example to get you started:
The output should be
Maybe you could simplify the code by removing all
ICustomObjectCreator
instances by simply using Autofac to create your objects directly.Update
The first approach works, but it does not take into account that you need to get a string to decide which kind of object you are creating (
type
).To get this to work you could the following:
CustomConverter
as generic.ResolveContractConverter
method to return an instance of the converter in case anyICustomObjectCreator
has been registered for the type.DefaultSettings
so that theAutofacContractResolver
will be used.See the following example:
The output should be
Here is the .NET Fiddle link for the sample.
Suppose an autofac setting like the following:
Then, suppose your class is like this:
Therefore, the usage of the resolver in deserialization could be like:
You can see more details in http://www.newtonsoft.com/json/help/html/DeserializeWithDependencyInjection.htm