1

This code works fine with default constructor. How can I create object from constructors with parameters?

private readonly JsonSerializer _serializer;

private static readonly IReadOnlyDictionary<TypeId, Type> _derivedTypes;
        static ByTypeIdConverter()
        {
            var baseType = typeof(T);
            var assemblies = AppDomain.CurrentDomain.GetAssemblies();

            _derivedTypes = (
                    from domainAssembly in AppDomain.CurrentDomain.GetAssemblies()
                    from assemblyType in domainAssembly.GetTypes()
                    where !assemblyType.IsAbstract && assemblyType.IsSubclassOf(baseType)
                    select assemblyType).ToDictionary(t => (TypeId)t);
        }

public override T? ReadJson(JsonReader reader, Type objectType, T? existingValue, bool hasExistingValue, JsonSerializer serializer)
{
    var jObject = JObject.Load(reader);
    var typeId = jObject["_t"]?.ToObject<TypeId>();

    if (typeId is null || !_derivedTypes.TryGetValue(typeId, out var classType))
        throw new JsonSerializationException("Failed to get derived class type from json or found type was not expected");

    var creator = _serializer.ContractResolver.ResolveContract(classType).DefaultCreator;

    if (creator is null)
    {
        throw new JsonSerializationException($"Failed create instance of type {classType.Name}");
    }

    var result = creator();
    _serializer.Populate(jObject.CreateReader(), result);

    return (T)result;
} 

Some additional information I have SomeBase class and custom JsonConverter for that base class. I simply deserialize like this:

JsonConvert.DeserializeObject<SomeBase>(jsonData);
Huseyn Zeynalov
  • 123
  • 2
  • 9
  • Where from would you like to get those constructor parameter values? Are there in the json string? Constants? – cly Mar 26 '21 at 13:48
  • Will this help you? https://stackoverflow.com/questions/23017716/json-net-how-to-deserialize-without-using-the-default-constructor – cly Mar 26 '21 at 13:51
  • I have added som details. Maybe this will more clarify problem – Huseyn Zeynalov Mar 26 '21 at 13:52
  • Yes I have seen this solution. Is there any other solution? Like generic way? In this example it is more static defined – Huseyn Zeynalov Mar 26 '21 at 13:54
  • If you are inside `JsonConverter.ReadJson()` you need to suspend the converter and recursively invoke `serializer.Deserialize()` to do what you want. It might be sufficient to stop using `JsonConverter` (if you are using it) because it's [implementation of `CanConvert`](https://github.com/JamesNK/Newtonsoft.Json/blob/master/Src/Newtonsoft.Json/JsonConverter.cs#L144) is **sealed**. Instead it *may* be enough to use the base class `JsonConverter`, overide `CanConvert(Type objectType)` and return `objectType == typeof(T)` not `typeof(T).IsAssignableFrom(objectType);`. – dbc Mar 26 '21 at 14:10
  • But we need to see a [mcve] showing your complete converter **and how you have applied it** to be sure. [How to call JsonConvert.DeserializeObject and disable a JsonConverter applied to a base type via `[JsonConverter]`?](https://stackoverflow.com/q/45547123/3744182) or [JSON.Net throws StackOverflowException when using `[JsonConvert()]`](https://stackoverflow.com/a/29720068/3744182) might be better duplicates depending upon whether the converter is applied to to some **property**, to base class/interface **type**, or in **settings**. – dbc Mar 26 '21 at 14:40
  • 2
    If you want to initialize a class using the constructors. Then you can just parse the JSON into a JObject and pass the parameters you want into the constructor. Then, if you still want to copy over all the values. you can use the PopulateObject method to copy over all the values. – John Mar 26 '21 at 15:01

1 Answers1

0

I creted uninitlized object. This helped me to solve my problem

if (creator is null)
                creator = () => RuntimeHelpers.GetUninitializedObject(classType);
Huseyn Zeynalov
  • 123
  • 2
  • 9