/// <summary> /// Tries to instantiate an object of a specific type. This performs /// application specific instantiation and subclasses should override /// this method to perform their own logic. If the instantiated object is /// null, then InstantiationData.Null should be returned. /// </summary> /// <param name="node">JSON node to create the instance from. This /// might be used to decide the type of the object or for the arguments /// of a constructor.</param> /// <param name="targetType">Target type of the object.</param> /// <param name="referingType">Refering type that is only set if this /// is a substitute type for another type.</param> /// <param name="options">Instantiation options.</param> /// <param name="deserializer">Deserializer to use for the instantiation.</param> protected virtual bool TryInstantiate( JSONNode node, Type targetType, Type referingType, NodeOptions options, Deserializer deserializer, out InstantiationData instantiationData) { instantiationData = InstantiationData.Null; return(false); }
private InstantiationData _InstantiateWithConstructor( JSONNode node, Type targetType, NodeOptions options, Deserializer deserializer) { if (node.IsNull || node.Tag == JSONNodeType.None) { return(InstantiationData.Null); } JSONObjectAttribute objectAttribute = Util.GetAttribute <JSONObjectAttribute> (targetType); bool useTupleFormat = objectAttribute != null ? objectAttribute.options.ShouldUseTupleFormat() : false; if (useTupleFormat && !node.IsArray) { throw new InstantiationException("Expected JSON array, found " + node.Tag); } else if (!useTupleFormat && !node.IsObject) { throw new InstantiationException("Expected JSON object, found " + node.Tag); } ConstructorInfo[] constructors = targetType.GetConstructors( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (ConstructorInfo constructorInfo in constructors) { var constructorAttribute = Util.GetAttribute <JSONConstructorAttribute> (constructorInfo); if (constructorAttribute != null) { return(_InstantiateWithConstructor(node, constructorInfo, deserializer, useTupleFormat)); } } try { InstantiationData instantiationData = new InstantiationData(); instantiationData.instantiatedObject = Activator.CreateInstance(targetType); instantiationData.needsDeserialization = node.Count != 0; return(instantiationData); } catch (Exception) { return(_HandleError(options, "Type " + targetType + " does not have a suitable constructor.")); } }
private InstantiationData _InstantiateWithConstructor( JSONNode node, ConstructorInfo constructorInfo, Deserializer deserializer, bool useTupleFormat) { ParameterInfo[] parameters = constructorInfo.GetParameters(); object[] parameterValues = new object[parameters.Length]; HashSet <string> ignoredKeys = new HashSet <string> (); for (int i = 0; i < parameterValues.Length; i++) { var nodeAttribute = Util.GetAttribute <JSONNodeAttribute> (parameters [i]); var restrictAttribute = Util.GetAttribute <RestrictTypeAttribute> (parameters [i]); string key = nodeAttribute != null && nodeAttribute.key != null ? nodeAttribute.key : parameters [i].Name; JSONNode parameterNode = useTupleFormat ? node [i] : node [key]; ObjectTypes restrictedTypes = restrictAttribute == null ? ObjectTypes.JSON : restrictAttribute.types; Type[] customTypes = restrictAttribute == null ? null : restrictAttribute.customTypes; parameterValues [i] = deserializer.Deserialize( parameterNode, parameters [i].ParameterType, nodeAttribute == null ? NodeOptions.Default : nodeAttribute.options, restrictedTypes, customTypes); if (!useTupleFormat) { ignoredKeys.Add(key); } } InstantiationData instantiationData = new InstantiationData(); instantiationData.instantiatedObject = constructorInfo.Invoke(parameterValues); instantiationData.needsDeserialization = !useTupleFormat && ignoredKeys.Count != node.Count; instantiationData.ignoredKeys = ignoredKeys; return(instantiationData); }