private OpenApiSchema CreateSchema(Type type, Queue <Type> referencedTypes) { // If Option<T> (F#), use the type argument if (type.IsFSharpOption()) { type = type.GetGenericArguments()[0]; } // Special handling for form binding types if (typeof(IFormFile).IsAssignableFrom(type)) { return(new OpenApiSchema { Type = "string", Format = "binary" }); } var jsonContract = _jsonContractResolver.ResolveContract(type); var createReference = !_options.CustomTypeMappings.ContainsKey(type) && type != typeof(object) && (// Type describes an object jsonContract is JsonObjectContract || // Type is self-referencing jsonContract.IsSelfReferencingArrayOrDictionary() || // Type is enum and opt-in flag set (type.GetTypeInfo().IsEnum&& _options.UseReferencedDefinitionsForEnums)); return(createReference ? CreateReferenceSchema(type, referencedTypes) : CreateInlineSchema(type, referencedTypes)); }
public override bool CanCreateSchemaFor(Type type, out bool shouldBeReferenced) { if (_contractResolver.ResolveContract(type) is JsonObjectContract) { shouldBeReferenced = true; return(true); } shouldBeReferenced = false; return(false); }
public override bool CanCreateSchemaFor(Type type, out bool shouldBeReferenced) { if (_contractResolver.ResolveContract(type) is JsonDictionaryContract jsonDictionaryContract) { shouldBeReferenced = (jsonDictionaryContract.DictionaryValueType == type); // to avoid circular references return(true); } shouldBeReferenced = false; return(false); }
private ApiType createType(Type type, Queue <Type> typeReferences) { var jsonContract = contractResolver.ResolveContract(type); var apiType = !primitiveTypeMappings.ContainsKey(type.Name) && type != typeof(object) && (jsonContract is JsonObjectContract || jsonContract.IsSelfReferencingArrayOrDictionary()) ? createReferenceType(type, typeReferences) : createInlineType(type, typeReferences, jsonContract); return(apiType); }
private Schema CreateSchema(Type type) { var jsonContract = _jsonContractResolver.ResolveContract(type); var createReference = !_options.CustomTypeMappings.ContainsKey(type) && type != typeof(object) && (jsonContract is JsonObjectContract || jsonContract.IsSelfReferencingArrayOrDictionary()); return(createReference ? CreateReferenceSchema(type) : CreateInlineSchema(type)); }
private IEnumerable <JsonProperty> GetTypeProperties(Type type, IEnumerable <JsonProperty> excludedProperties) { if (_contractResolver.ResolveContract(type) is JsonObjectContract contract) { return(contract.Properties .Where(p => excludedProperties.All(ep => ep.PropertyName != p.PropertyName)) .ToList()); } return(new JsonProperty[] { }); }
public override bool CanCreateSchemaFor(Type type, out bool shouldBeReferenced) { if (_contractResolver.ResolveContract(type) is JsonObjectContract) { var shouldBePolymorphic = _generatorOptions.GeneratePolymorphicSchemas && _generatorOptions.SubTypesResolver(type).Any(); shouldBeReferenced = !(type == typeof(object) || shouldBePolymorphic); return(true); } shouldBeReferenced = false; return(false); }
public override IAdapter Create(object target, IContractResolver contractResolver) { if (target == null) { throw new ArgumentNullException(nameof(target)); } if (contractResolver == null) { throw new ArgumentNullException(nameof(contractResolver)); } var jsonContract = contractResolver.ResolveContract(target.GetType()); if (target is IList) { return(new ListAdapter()); } else if (jsonContract is JsonDictionaryContract jsonDictionaryContract) { var type = typeof(DictionaryAdapter <,>).MakeGenericType(jsonDictionaryContract.DictionaryKeyType, jsonDictionaryContract.DictionaryValueType); return((IAdapter)Activator.CreateInstance(type)); } else if (jsonContract is JsonDynamicContract) { return(new DynamicObjectAdapter()); } else { return(new AwarePocoAdapter()); } }
protected override bool TryGetJsonProperty(object target, IContractResolver contractResolver, string segment, out JsonProperty jsonProperty) { if (contractResolver.ResolveContract(target.GetType()) is JsonObjectContract jsonObjectContract) { var pocoProperty = jsonObjectContract .Properties .FirstOrDefault(p => string.Equals(p.PropertyName, segment, StringComparison.OrdinalIgnoreCase)); if (pocoProperty != null) { jsonProperty = pocoProperty; if (jsonProperty.Writable && pocoProperty.AttributeProvider.GetAttributes(false) .Any(a => a is ForbidPatchAttribute)) { jsonProperty.Writable = false; } return(true); } } jsonProperty = null; return(false); }
public OpenApiSchema GenerateSchemaFor(Type type, SchemaRepository schemaRepository) { if (_options.CustomTypeMappings.ContainsKey(type)) { return(_options.CustomTypeMappings[type]()); } if (KnownTypeMappings.ContainsKey(type)) { return(KnownTypeMappings[type]()); } if (type.IsNullable() || type.IsFSharpOption()) // unwrap nullables { type = type.GenericTypeArguments[0]; } var jsonContract = _jsonContractResolver.ResolveContract(type); if (type.IsEnum || // enum (jsonContract is JsonObjectContract) || // regular object (jsonContract is JsonArrayContract && ((JsonArrayContract)jsonContract).CollectionItemType == jsonContract.UnderlyingType) || // self-referencing array (jsonContract is JsonDictionaryContract && ((JsonDictionaryContract)jsonContract).DictionaryValueType == jsonContract.UnderlyingType)) // self-referencing dictionary { return(GenerateReferenceSchemaFor(type, schemaRepository, jsonContract)); } return(GenerateDefinitionSchemaFor(type, schemaRepository, jsonContract)); }
/// <inheritdoc /> public override JsonContract ResolveContract(Type type) { var contract = _existingContractResolver?.ResolveContract(type); if (contract?.Converter != null) { return(contract); } if (contract == null) { contract = base.ResolveContract(type); } if (type == typeof(DateTime) || type == typeof(DateTime?)) { contract.Converter = _forceDateTimeKindOverride == DateTimeKind.Local ? JsonDateTimeTickConverter.LocalDateTimeKindDefault : JsonDateTimeTickConverter.Default; } else if (type == typeof(DateTimeOffset) || type == typeof(DateTimeOffset?)) { contract.Converter = JsonDateTimeOffsetTickConverter.Default; } return(contract); }
protected static bool CanConvert(IContractResolver contractResolver, Type objectType, out Type elementType, out JsonProperty keyProperty) { if (objectType.IsArray) { // Not implemented for arrays, since they cannot be resized. elementType = null; keyProperty = null; return(false); } var elementTypes = objectType.GetIListItemTypes().ToList(); if (elementTypes.Count != 1) { elementType = null; keyProperty = null; return(false); } elementType = elementTypes[0]; var contract = contractResolver.ResolveContract(elementType) as JsonObjectContract; if (contract == null) { keyProperty = null; return(false); } keyProperty = contract.Properties.Where(p => p.AttributeProvider.GetAttributes(typeof(JsonMergeKeyAttribute), true).Count > 0).SingleOrDefault(); return(keyProperty != null); }
public virtual bool TryTraverse( object target, string segment, IContractResolver contractResolver, out object nextTarget, out string errorMessage) { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary <TKey, TValue>)target; if (!TryConvertKey(key, out var convertedKey, out errorMessage)) { nextTarget = null; return(false); } if (dictionary.TryGetValue(convertedKey, out var valueAsT)) { nextTarget = valueAsT; errorMessage = null; return(true); } else { nextTarget = null; errorMessage = null; return(false); } }
private static IDataTypeInfo GetDataTypeInfo(Type propertyType, IContractResolver contractResolver) { bool IsNullableType(Type type) => type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable <>); if (PrimitiveTypeMap.TryGetValue(propertyType, out DataType dataType)) { return(DataTypeInfo.Simple(dataType)); } else if (IsNullableType(propertyType)) { return(GetDataTypeInfo(propertyType.GenericTypeArguments[0], contractResolver)); } else if (TryGetEnumerableElementType(propertyType, out Type elementType)) { IDataTypeInfo elementTypeInfo = GetDataTypeInfo(elementType, contractResolver); return(DataTypeInfo.AsCollection(elementTypeInfo)); } else if (contractResolver.ResolveContract(propertyType) is JsonObjectContract jsonContract) { return(DataTypeInfo.Complex(DataType.Complex, propertyType, jsonContract)); } else { return(DataTypeInfo.Unknown); } }
public virtual bool TryGet( object target, string segment, IContractResolver contractResolver, out object value, out string errorMessage) { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary <TKey, TValue>)target; if (!TryConvertKey(key, out var convertedKey, out errorMessage)) { value = null; return(false); } if (!dictionary.TryGetValue(convertedKey, out var valueAsT)) { value = null; errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); return(false); } value = valueAsT; errorMessage = null; return(true); }
public virtual bool TryReplace( object target, string segment, IContractResolver contractResolver, object value, out string errorMessage) { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary <TKey, TValue>)target; if (!TryConvertKey(key, out var convertedKey, out errorMessage)) { return(false); } // As per JsonPatch spec, the target location must exist for remove to be successful if (!dictionary.ContainsKey(convertedKey)) { errorMessage = Resources.FormatTargetLocationAtPathSegmentNotFound(segment); return(false); } if (!TryConvertValue(value, out var convertedValue, out errorMessage)) { return(false); } dictionary[convertedKey] = convertedValue; errorMessage = null; return(true); }
public JsonContract ResolveContract(Type type) { if (type.GetTypeInfo().Assembly.Equals(_assembly)) return _defaultContractSerializer.ResolveContract(type); return _camelCaseContractResolver.ResolveContract(type); }
private async Task VisitPropertiesAsync(object obj, string path, ISet <object> checkedObjects) { if (_contractResolver.ResolveContract(obj.GetType()) is JsonObjectContract contract) { foreach (var property in contract.Properties.Where(p => !p.Ignored && p.ShouldSerialize?.Invoke(obj) != false)) { var value = property.ValueProvider.GetValue(obj); if (value != null) { await VisitAsync(value, path + "/" + property.PropertyName, property.PropertyName, checkedObjects, o => property.ValueProvider.SetValue(obj, o)).ConfigureAwait(false); } } } else { foreach (var member in ReflectionCache.GetPropertiesAndFields(obj.GetType()).Where(p => p.MemberInfo is PropertyInfo && (!(obj is JsonSchema4) || !_jsonSchemaProperties.Contains(p.MemberInfo.Name)) && (!(obj is IDictionary) || (p.MemberInfo.DeclaringType == obj.GetType())) && // only check additional properties of dictionary p.CanRead && p.IsIndexer == false && p.CustomAttributes.JsonIgnoreAttribute == null)) { var value = member.GetValue(obj); if (value != null) { await VisitAsync(value, path + "/" + member.GetName(), member.GetName(), checkedObjects, o => member.SetValue(obj, o)).ConfigureAwait(false); } } } }
static bool CanConvert(IContractResolver contractResolver, Type objectType, out Type elementType, out JsonProperty keyProperty) { elementType = objectType.GetListType(); if (elementType == null) { keyProperty = null; return(false); } var contract = contractResolver.ResolveContract(elementType) as JsonObjectContract; if (contract == null) { keyProperty = null; return(false); } //keyProperty = contract.Properties.Where(p => p.AttributeProvider.GetAttributes(typeof(JsonMergeKeyAttribute), true).Count > 0).SingleOrDefault(); keyProperty = null; foreach (var p in contract.Properties) { if (p.PropertyName == "Id") { keyProperty = p; } } return(keyProperty != null); }
protected override bool TryGetJsonProperty(object target, IContractResolver contractResolver, string segment, out JsonProperty jsonProperty) { if (contractResolver.ResolveContract(target.GetType()) is JsonObjectContract jsonObjectContract) { var pocoProperty = jsonObjectContract .Properties .FirstOrDefault(p => string.Equals(p.PropertyName, segment, StringComparison.OrdinalIgnoreCase)); // Property must have PatchableAttribute or patch operation cannot be applied. if (pocoProperty != null) { jsonProperty = pocoProperty; // If the property is writable, but it doesn't have the PatchableAttribute, then make it not writable. if (jsonProperty.Writable && !pocoProperty.AttributeProvider.GetAttributes(false).Any(a => a is PatchableAttribute)) { jsonProperty.Writable = false; } return(true); } } jsonProperty = null; return(false); }
public ApiModel ResolveApiModelFor(Type type) { // If it's nullable, use the inner value type var underlyingType = type.IsNullable(out Type valueType) ? valueType : type; var jsonContract = _jsonContractResolver.ResolveContract(underlyingType); if (jsonContract is JsonPrimitiveContract jsonPrimitiveContract) { return(ResolveApiPrimitive(jsonPrimitiveContract)); } if (jsonContract is JsonDictionaryContract jsonDictionaryContract) { return(ResolveApiDictionary(jsonDictionaryContract)); } if (jsonContract is JsonArrayContract jsonArrayContract) { return(ResolveApiArray(jsonArrayContract)); } if (jsonContract is JsonObjectContract jsonObjectContract) { return(ResolveApiObject(jsonObjectContract)); } return(new ApiModel(jsonContract.UnderlyingType)); }
private static IEnumerable <Expression> CreateWriteValueExpressions(ParameterExpression writer, ParameterExpression value, ParameterExpression serializer, IContractResolver contractResolver) { var contract = contractResolver.ResolveContract(typeof(T)) as JsonObjectContract; if (contract != null) { foreach (var property in contract.Properties) { var getValueMethod = typeof(IValueProvider).GetMethod("GetValue"); var valueProvider = Expression.Constant(property.ValueProvider); yield return (Expression.Call(writer, LinkConverter.WritePropertyName, Expression.Constant(property.PropertyName))); var getValue = Expression.Call(valueProvider, getValueMethod, value); yield return(Expression.Call(serializer, LinkConverter.Serialize, writer, getValue)); } } else { foreach (var info in typeof(T).GetProperties()) { yield return (Expression.Call(writer, LinkConverter.WritePropertyName, Expression.Constant(ToCamelCase(info.Name)))); var getValue = Expression.Convert(Expression.Property(value, info), typeof(object)); yield return(Expression.Call(serializer, LinkConverter.Serialize, writer, getValue)); } } }
public virtual bool TryAdd( object target, string segment, IContractResolver contractResolver, object value, out string errorMessage) { var contract = (JsonDictionaryContract)contractResolver.ResolveContract(target.GetType()); var key = contract.DictionaryKeyResolver(segment); var dictionary = (IDictionary <TKey, TValue>)target; // As per JsonPatch spec, if a key already exists, adding should replace the existing value if (!TryConvertKey(key, out var convertedKey, out errorMessage)) { return(false); } if (!TryConvertValue(value, out var convertedValue, out errorMessage)) { return(false); } dictionary[convertedKey] = convertedValue; errorMessage = null; return(true); }
private static string GetJsonPropertyName(Type type, string propertyName) { var contract = DefaultResolver.ResolveContract(type) as JsonObjectContract; var property = contract.Properties.Single(p => p.UnderlyingName == propertyName); return(property.PropertyName); }
private ICollection <FieldIndexingInfo> GenerateFieldIndexingInfos(Type type, int levels, Func <Type, JsonProperty, bool> propertySelector) { var fields = new Collection <FieldIndexingInfo>(); if (_contractResolver.ResolveContract(type) is JsonObjectContract contract) { foreach (var property in contract.Properties) { if (propertySelector?.Invoke(type, property) != false) { var searchAttribute = property.AttributeProvider .GetAttributes(true) .OfType <PictureparkSearchAttribute>() .SingleOrDefault(); var field = new FieldIndexingInfo { Id = property.PropertyName, SimpleSearch = searchAttribute?.SimpleSearch ?? false, Index = searchAttribute?.Index ?? false, Boost = searchAttribute?.Boost ?? 0.0, }; fields.Add(field); ApplyPictureparkSchemaIndexingAttribute(property, field); if (levels > 0) { var propertyType = property.PropertyType.GenericTypeArguments.Any() ? property.PropertyType.GenericTypeArguments.First() : property.PropertyType; var subFields = GenerateFieldIndexingInfos(propertyType, levels - 1, propertySelector); if (subFields != null && subFields.Any()) { field.RelatedSchemaIndexing = new SchemaIndexingInfo { Fields = subFields }; } } } } } return(fields); }
public void SerializeDynamicObject() { TestDynamicObject dynamicObject = new TestDynamicObject(); dynamicObject.Explicit = true; dynamic d = dynamicObject; d.Int = 1; d.Decimal = 99.9d; d.ChildObject = new DynamicChildObject(); Dictionary <string, object> values = new Dictionary <string, object>(); IContractResolver c = DefaultContractResolver.Instance; JsonDynamicContract dynamicContract = (JsonDynamicContract)c.ResolveContract( dynamicObject.GetType() ); foreach (string memberName in dynamicObject.GetDynamicMemberNames()) { object value; dynamicContract.TryGetMember(dynamicObject, memberName, out value); values.Add(memberName, value); } Assert.AreEqual(d.Int, values["Int"]); Assert.AreEqual(d.Decimal, values["Decimal"]); Assert.AreEqual(d.ChildObject, values["ChildObject"]); string json = JsonConvert.SerializeObject(dynamicObject, Formatting.Indented); StringAssert.AreEqual( @"{ ""Explicit"": true, ""Decimal"": 99.9, ""Int"": 1, ""ChildObject"": { ""Text"": null, ""Integer"": 0 } }", json ); TestDynamicObject newDynamicObject = JsonConvert.DeserializeObject <TestDynamicObject>( json ); Assert.AreEqual(true, newDynamicObject.Explicit); d = newDynamicObject; Assert.AreEqual(99.9, d.Decimal); Assert.AreEqual(1, d.Int); Assert.AreEqual(dynamicObject.ChildObject.Integer, d.ChildObject.Integer); Assert.AreEqual(dynamicObject.ChildObject.Text, d.ChildObject.Text); }
public JsonContract ResolveContract(Type type) { // We can't use camelcasing on any internal SignalR types // so these must be explicitly excluded return(type.Assembly.Equals(_assembly) ? _defaultContractSerializer.ResolveContract(type) : _camelCaseContractResolver.ResolveContract(type)); }
private Schema CreateSchema(Type type, Queue <Type> referencedTypes) { var jsonContract = _jsonContractResolver.ResolveContract(type); var createReference = !_settings.CustomTypeMappings.ContainsKey(type) && type != typeof(object) && (// Type describes an object jsonContract is JsonObjectContract || // Type is self-referencing jsonContract.IsSelfReferencingArrayOrDictionary() || // Type is enum and opt-in flag set (type.IsEnumType() && _settings.UseReferencedDefinitionsForEnums)); return(createReference ? CreateReferenceSchema(type, referencedTypes) : CreateInlineSchema(type, referencedTypes)); }
public JsonContract ResolveContract(Type type) { if (type.Assembly.Equals(_signalRAssembly)) { return(_defaultContractResolver.ResolveContract(type)); } return(_camelCaseContractResolver.ResolveContract(type)); }
public JsonContract ResolveContract(Type type) { if (type.Assembly.Equals(assembly)) { return(defaultContractSerializer.ResolveContract(type)); } return(camelCaseContractResolver.ResolveContract(type)); }
public static JsonPatchProperty FindPropertyAndParent( object targetObject, string propertyPath, IContractResolver contractResolver) { try { var splitPath = propertyPath.Split('/'); // skip the first one if it's empty var startIndex = (string.IsNullOrWhiteSpace(splitPath[0]) ? 1 : 0); for (int i = startIndex; i < splitPath.Length; i++) { var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType()); foreach (var property in jsonContract.Properties) { if (string.Equals(property.PropertyName, splitPath[i], StringComparison.OrdinalIgnoreCase)) { if (i == (splitPath.Length - 1)) { return new JsonPatchProperty(property, targetObject); } else { targetObject = property.ValueProvider.GetValue(targetObject); // if property is of IList type then get the array index from splitPath and get the // object at the indexed position from the list. if (typeof(IList).GetTypeInfo().IsAssignableFrom(property.PropertyType.GetTypeInfo())) { var index = int.Parse(splitPath[++i]); targetObject = ((IList)targetObject)[index]; } } break; } } } return null; } catch (Exception) { // will result in JsonPatchException in calling class, as expected return null; } }
public ObjectTreeAnalysisResult( object objectToSearch, string propertyPath, IContractResolver contractResolver) { // construct the analysis result. // split the propertypath, and if necessary, remove the first // empty item (that's the case when it starts with a "/") var propertyPathTree = propertyPath.Split( new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); // we've now got a split up property tree "base/property/otherproperty/..." int lastPosition = 0; object targetObject = objectToSearch; for (int i = 0; i < propertyPathTree.Length; i++) { lastPosition = i; // if the current target object is an ExpandoObject (IDictionary<string, object>), // we cannot use the ContractResolver. var dictionary = targetObject as IDictionary<string, object>; if (dictionary != null) { // find the value in the dictionary if (dictionary.ContainsCaseInsensitiveKey(propertyPathTree[i])) { var possibleNewTargetObject = dictionary.GetValueForCaseInsensitiveKey(propertyPathTree[i]); // unless we're at the last item, we should set the targetobject // to the new object. If we're at the last item, we need to stop if (i != propertyPathTree.Length - 1) { targetObject = possibleNewTargetObject; } } else { break; } } else { // if the current part of the path is numeric, this means we're trying // to get the propertyInfo of a specific object in an array. To allow // for this, the previous value (targetObject) must be an IEnumerable, and // the position must exist. int numericValue = -1; if (int.TryParse(propertyPathTree[i], out numericValue)) { var element = GetElementAtFromObject(targetObject, numericValue); if (element != null) { targetObject = element; } else { break; } } else { var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType()); // does the property exist? var attemptedProperty = jsonContract .Properties .FirstOrDefault(p => string.Equals(p.PropertyName, propertyPathTree[i], StringComparison.OrdinalIgnoreCase)); if (attemptedProperty != null) { // unless we're at the last item, we should continue searching. // If we're at the last item, we need to stop if ((i != propertyPathTree.Length - 1)) { targetObject = attemptedProperty.ValueProvider.GetValue(targetObject); } } else { // property cannot be found, and we're not working with dynamics. // Stop, and return invalid path. break; } } } } if (propertyPathTree.Length - lastPosition != 1) { IsValidPathForAdd = false; IsValidPathForRemove = false; return; } // two things can happen now. The targetproperty can be an IDictionary - in that // case, it's valid for add if there's 1 item left in the propertyPathTree. // // it can also be a property info. In that case, if there's nothing left in the path // tree we're at the end, if there's one left we can try and set that. if (targetObject is IDictionary<string, object>) { UseDynamicLogic = true; Container = (IDictionary<string, object>)targetObject; IsValidPathForAdd = true; PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1]; // to be able to remove this property, it must exist IsValidPathForRemove = Container.ContainsCaseInsensitiveKey(PropertyPathInParent); } else if (targetObject is IList) { UseDynamicLogic = false; int index; if (!Int32.TryParse(propertyPathTree[propertyPathTree.Length - 1], out index)) { // We only support indexing into a list IsValidPathForAdd = false; IsValidPathForRemove = false; return; } IsValidPathForAdd = true; IsValidPathForRemove = ((IList)targetObject).Count > index; PropertyPathInParent = propertyPathTree[propertyPathTree.Length - 1]; } else { UseDynamicLogic = false; var property = propertyPathTree[propertyPathTree.Length - 1]; var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(targetObject.GetType()); var attemptedProperty = jsonContract .Properties .FirstOrDefault(p => string.Equals(p.PropertyName, property, StringComparison.OrdinalIgnoreCase)); if (attemptedProperty == null) { IsValidPathForAdd = false; IsValidPathForRemove = false; } else { IsValidPathForAdd = true; IsValidPathForRemove = true; JsonPatchProperty = new JsonPatchProperty(attemptedProperty, targetObject); PropertyPathInParent = property; } } }
public ScimPatchObjectAnalysis( ScimServerConfiguration serverConfiguration, object objectToSearch, string filter, IContractResolver contractResolver, Operation operation) { _ServerConfiguration = serverConfiguration; _ContractResolver = contractResolver; _Operation = operation; PatchMembers = new List<PatchMember>(); /* ScimFilter.cs will handle normalizing the actual path string. Examples: "path":"members" "path":"name.familyName" "path":"addresses[type eq \"work\"]" "path":"members[value eq \"2819c223-7f76-453a-919d-413861904646\"]" "path":"members[value eq \"2819c223-7f76-453a-919d-413861904646\"].displayName" Once normalized, associate each resource member with its filter (if present). This is represented as a PathMember, which is essentially a tuple of <memberName, memberFilter?> */ var pathTree = new ScimFilter(_ServerConfiguration.ResourceExtensionSchemas.Keys, filter).Paths.ToList(); var lastPosition = 0; var nodes = GetAffectedMembers(pathTree, ref lastPosition, new Node(objectToSearch, null)); if ((pathTree.Count - lastPosition) > 1) { IsValidPathForAdd = false; IsValidPathForRemove = false; return; } foreach (var node in nodes) { var attribute = node.Target as MultiValuedAttribute; JsonProperty attemptedProperty; if (attribute != null && PathIsMultiValuedEnumerable(pathTree[pathTree.Count - 1].Path, node, out attemptedProperty)) { /* Check if we're at a MultiValuedAttribute. If so, then we'll return a special PatchMember. This is because our actual target is an element within an enumerable. (e.g. User->Emails[element]) So a PatchMember must have three pieces of information: (following the example above) > Parent (User) > PropertyPath (emails) > Actual Target (email instance/element) */ UseDynamicLogic = false; IsValidPathForAdd = true; IsValidPathForRemove = true; PatchMembers.Add( new PatchMember( pathTree[pathTree.Count - 1].Path, new JsonPatchProperty(attemptedProperty, node.Parent), node.Target)); } else { UseDynamicLogic = false; var jsonContract = (JsonObjectContract)contractResolver.ResolveContract(node.Target.GetType()); attemptedProperty = jsonContract.Properties.GetClosestMatchProperty(pathTree[pathTree.Count - 1].Path); if (attemptedProperty == null) { IsValidPathForAdd = false; IsValidPathForRemove = false; } else { IsValidPathForAdd = true; IsValidPathForRemove = true; PatchMembers.Add( new PatchMember( pathTree[pathTree.Count - 1].Path, new JsonPatchProperty(attemptedProperty, node.Target))); } } } }