public InstanceDescriptorFactory([NotNull] IPropertyReflector propertyReflector, [NotNull] IPropertyValueFactoryProvider propertyValueFactoryProvider, [NotNull] IPropertyValueHandlerFactory propertyValueHandlerFactory, [NotNull] ITypeAliasWalker typeAliasWalker) { if (propertyReflector == null) { throw new ArgumentNullException(nameof(propertyReflector)); } if (propertyValueFactoryProvider == null) { throw new ArgumentNullException(nameof(propertyValueFactoryProvider)); } if (propertyValueHandlerFactory == null) { throw new ArgumentNullException(nameof(propertyValueHandlerFactory)); } if (typeAliasWalker == null) { throw new ArgumentNullException(nameof(typeAliasWalker)); } this.propertyReflector = propertyReflector; this.propertyValueFactoryProvider = propertyValueFactoryProvider; this.propertyValueHandlerFactory = propertyValueHandlerFactory; this.typeAliasWalker = typeAliasWalker; }
private static IEnumerable <PropertyInfo> AnnotatedPropertiesCache(IPropertyReflector reflector, Type workItemType, Type attributeType) { if (AnnotatedProperties.TryGetValue(workItemType.TypeHandle, out ConcurrentDictionary <RuntimeTypeHandle, IEnumerable <PropertyInfo> > f)) { if (f.TryGetValue(attributeType.TypeHandle, out IEnumerable <PropertyInfo> pis)) { return(pis); } pis = reflector .GetProperties(workItemType) .Where(prop => reflector.GetCustomAttributes(prop, attributeType).Any()) .ToArray(); f[attributeType.TypeHandle] = pis; return(pis); } var pis2 = reflector.GetProperties(workItemType) .Where(prop => reflector.GetCustomAttributes(prop, attributeType).Any()) .ToArray(); AnnotatedProperties[workItemType.TypeHandle] = new ConcurrentDictionary <RuntimeTypeHandle, IEnumerable <PropertyInfo> >( new[] { new KeyValuePair <RuntimeTypeHandle, IEnumerable <PropertyInfo> >( attributeType.TypeHandle, pis2 ) }); return(pis2); }
/// <summary> /// Gets the <see cref="IPropertyReflector"/> properties that make up the unique key (lazy-loaded and cached for performance). /// </summary> /// <param name="ier">The parent <see cref="IEntityReflector"/>.</param> /// <returns>The <see cref="IPropertyReflector"/> properties.</returns> public IPropertyReflector[] GetPropertyReflectors(IEntityReflector ier) { if (propertyReflectors != null) { return(propertyReflectors); } lock (_lock) { if (propertyReflectors == null) { var prs = new IPropertyReflector[Properties.Length]; for (int i = 0; i < Properties.Length; i++) { prs[i] = ier.GetProperty(Properties[i]); if (prs[i] == null) { // Special case where the unique key may be a reference data type; i.e. points to the 'NameSid' property. prs[i] = ier.GetProperty(Properties[i] + "Sid"); if (prs[i] == null) { throw new InvalidOperationException($"Type '{ier.Type.Name}' references a UniqueKey Property '{Properties[i]}' that does not exist."); } } } propertyReflectors = prs; } } return(propertyReflectors); }
public TypeAliasWalker(IPropertyReflector propertyReflector) : base(propertyReflector) { this.ReflectBaseTypes = true; this.ReflectInterfaces = true; this.ReflectProperties = false; }
/// <summary> /// Initializes a new instance of the <see cref="TypeWalker"/> class. /// </summary> /// <param name="propertyReflector">The <see cref="IPropertyReflector"/> for property retrieval.</param> /// <exception cref="ArgumentNullException">The value of '<paramref name="propertyReflector"/>' cannot be null.</exception> protected TypeWalker([NotNull] IPropertyReflector propertyReflector) { if (propertyReflector == null) { throw new ArgumentNullException(nameof(propertyReflector)); } this.propertyReflector = propertyReflector; this.ReflectProperties = true; }
/// <summary> /// Updates the array value. /// </summary> private static JsonEntityMergeResult UpdateArrayValue(IPropertyReflector pr, object entity, IEnumerable curVal, IEnumerable newVal) { if (pr.ComplexTypeReflector.CompareSequence(newVal, curVal)) { return(JsonEntityMergeResult.SuccessNoChanges); } pr.ComplexTypeReflector.SetValue(entity, newVal); return(JsonEntityMergeResult.SuccessWithChanges); }
public InstanceResolutionWalker([NotNull] IPropertyReflector propertyReflector, [NotNull, ImportMany(typeof(IPropertyValueResolver))] IEnumerable <IPropertyValueResolver> propertyValueResolvers, [NotNull] ITypeInstanciator typeInstanciator) : base(propertyReflector) { if (propertyValueResolvers == null) { throw new ArgumentNullException(nameof(propertyValueResolvers)); } if (typeInstanciator == null) { throw new ArgumentNullException(nameof(typeInstanciator)); } this.propertyValueResolvers = propertyValueResolvers; this.typeInstanciator = typeInstanciator; }
/// <summary> /// Apply the merge from the json to the entity value as a more complex type. /// </summary> private static JsonEntityMergeResult MergeApplyComplex(JsonEntityMergeArgs args, IPropertyReflector pr, JProperty jp, object entity) { if (jp.Value.Type == JTokenType.Null) { return(pr.SetValue(entity, null) ? JsonEntityMergeResult.SuccessWithChanges : JsonEntityMergeResult.SuccessNoChanges); } // Update the sub-entity. if (pr.ComplexTypeReflector !.ComplexTypeCode == ComplexTypeCode.Object) { if (jp.Value.Type != JTokenType.Object) { return(args.Log(MessageItem.CreateMessage(jp.Path, MessageType.Error, $"The JSON token is malformed and could not be parsed."))); } var hasChanged = true; var current = pr.PropertyExpression.GetValue(entity); if (current == null) { current = pr.NewValue(entity).value; } else { hasChanged = false; } var mr = MergeApply(args, pr.GetEntityReflector() !, jp.Value, current !); return(mr == JsonEntityMergeResult.SuccessNoChanges ? (hasChanged ? JsonEntityMergeResult.SuccessWithChanges : JsonEntityMergeResult.SuccessNoChanges) : mr); }
public PropertyInspector(IPropertyReflector reflector) { _reflector = reflector; }
/// <summary> /// Apply the merge using the UniqueKey to match items between JSON and entity. /// </summary> private static JsonEntityMergeResult MergeApplyUniqueKeyItems(JsonEntityMergeArgs args, IPropertyReflector pr, JProperty jp, object entity) { var hasError = false; var hasChanges = false; var count = 0; var ukc = (UniqueKeyConfig)pr.Tag; var lo = new List <object>(); var ier = pr.GetItemEntityReflector(); // Determine the unique key for a comparison. var ukpr = ukc.GetPropertyReflectors(ier); // Get the current value to update. var current = (IEnumerable)pr.PropertyExpression.GetValue(entity); if (current == null) { hasChanges = true; } // Merge each item into the new collection. foreach (var ji in jp.Values()) { // Check not null. if (ji.Type != JTokenType.Object) { hasError = true; args.Log(MessageItem.CreateErrorMessage(ji.Path, "The JSON token must be an object where Unique Key value(s) are required.")); continue; } // Generate the unique key from the json properties. bool skip = false; var uk = new object[ukpr.Length]; for (int i = 0; i < ukc.Properties.Length; i++) { var jk = ji[ukpr[i].JsonName]; if (jk == null) { hasError = skip = true; args.Log(MessageItem.CreateErrorMessage(ji.Path, $"The JSON object must specify the '{ukpr[i].JsonName}' token as required for the unique key.")); break; } try { uk[i] = ukpr[i].GetJtokenValue(jk); } catch (FormatException fex) { hasError = skip = true; args.Log(MessageItem.CreateMessage(jk.Path, MessageType.Error, $"The JSON token is malformed: {fex.Message}")); break; } catch (Exception) { throw; } } if (skip) { continue; } // Get existing by unique key. var uniqueKey = new UniqueKey(uk); var item = current == null ? null : ukc.IsEntityBaseCollection ? ((IEntityBaseCollection)current).GetByUniqueKey(uniqueKey) : current.OfType <EntityBase>().FirstOrDefault(x => uniqueKey.Equals(x.UniqueKey)); // Create new if not found. if (item == null) { hasChanges = true; item = pr.ComplexTypeReflector.CreateItemValue(); } // Update. count++; var mr = MergeApply(args, ier, ji, item); if (mr == JsonEntityMergeResult.Error) { hasError = true; } else { if (mr == JsonEntityMergeResult.SuccessWithChanges) { hasChanges = true; } lo.Add(item); } } if (hasError) { return(JsonEntityMergeResult.Error); } // Confirm nothing was deleted (only needed where nothing changed so far). if (!hasChanges && count == (ukc.IsEntityBaseCollection ? ((IEntityBaseCollection)current).Count : current.OfType <EntityBase>().Count())) { return(JsonEntityMergeResult.SuccessNoChanges); } pr.ComplexTypeReflector.SetValue(entity, lo); return(JsonEntityMergeResult.SuccessWithChanges); }
/// <summary> /// Apply the merge as a full collection replacement; there is <b>no</b> way to detect changes or perform partial property update. /// </summary> private static JsonEntityMergeResult MergeApplyComplexItems(JsonEntityMergeArgs args, IPropertyReflector pr, JProperty jp, object entity) { var hasError = false; var lo = new List <object>(); var ier = pr.GetItemEntityReflector(); foreach (var ji in jp.Values()) { if (ji.Type == JTokenType.Null) { lo.Add(null); continue; } var ival = pr.ComplexTypeReflector.CreateItemValue(); if (MergeApply(args, ier, ji, ival) == JsonEntityMergeResult.Error) { hasError = true; } else { lo.Add(ival); } } if (hasError) { return(JsonEntityMergeResult.Error); } pr.ComplexTypeReflector.SetValue(entity, lo); return(JsonEntityMergeResult.SuccessWithChanges); }
/// <summary> /// Apply the merge from the json to the entity value as a more complex type. /// </summary> private static JsonEntityMergeResult MergeApplyComplex(JsonEntityMergeArgs args, IPropertyReflector pr, JProperty jp, object entity) { if (jp.Value.Type == JTokenType.Null) { return(pr.SetValue(entity, null) ? JsonEntityMergeResult.SuccessWithChanges : JsonEntityMergeResult.SuccessNoChanges); } // Update the sub-entity. if (pr.ComplexTypeReflector.ComplexTypeCode == ComplexTypeCode.Object) { if (jp.Value.Type != JTokenType.Object) { return(args.Log(MessageItem.CreateMessage(jp.Path, MessageType.Error, $"The JSON token is malformed and could not be parsed."))); } var hasChanged = true; var current = pr.PropertyExpression.GetValue(entity); if (current == null) { current = pr.NewValue(entity).value; } else { hasChanged = false; } var mr = MergeApply(args, pr.GetEntityReflector(), jp.Value, current); return(mr == JsonEntityMergeResult.SuccessNoChanges ? (hasChanged ? JsonEntityMergeResult.SuccessWithChanges : JsonEntityMergeResult.SuccessNoChanges) : mr); } else { // Ensure we are dealing with an array. if (jp.Value.Type != JTokenType.Array) { return(args.Log(MessageItem.CreateMessage(jp.Path, MessageType.Error, $"The JSON token is malformed and could not be parsed."))); } // Where empty array then update as such. if (!jp.Value.HasValues) { return(UpdateArrayValue(args, pr, entity, (IEnumerable)pr.PropertyExpression.GetValue(entity), (IEnumerable)pr.ComplexTypeReflector.CreateValue())); } // Handle array with primitive types. if (!pr.ComplexTypeReflector.IsItemComplexType) { var lo = new List <object>(); foreach (var iv in jp.Value.Values()) { lo.Add(iv.ToObject(pr.ComplexTypeReflector.ItemType)); } return(UpdateArrayValue(args, pr, entity, (IEnumerable)pr.PropertyExpression.GetValue(entity), (IEnumerable)pr.ComplexTypeReflector.CreateValue(lo))); } // Finally, handle array with complex entity items. return((pr.Tag == null) ? MergeApplyComplexItems(args, pr, jp, entity) : MergeApplyUniqueKeyItems(args, pr, jp, entity)); } }
/// <summary> /// Creates a new instance of <see cref="AttributeMapperStrategy"/> with the specified <paramref name="propertyReflector"/>. /// </summary> /// <param name="propertyReflector">An instance of <see cref="IPropertyReflector"/>.</param> public AttributeMapperStrategy([NotNull] IPropertyReflector propertyReflector) : this(new PropertyInspector(propertyReflector)) { }
public PropertyInspector([NotNull] IPropertyReflector reflector) { _reflector = reflector ?? throw new ArgumentNullException(nameof(reflector)); }
/// <summary> /// Creates a new instance of <see cref="NoExceptionAttributeMapperStrategy"/> with the specified <paramref name="propertyReflector"/>. /// </summary> /// <param name="propertyReflector">An instance of <see cref="IPropertyReflector"/>.</param> public NoExceptionAttributeMapperStrategy([NotNull] IPropertyReflector propertyReflector) : base(propertyReflector) { }
static PropertyReflectorFactory() { PropertyReflectorFactory.ExpandoObjectPropertyReflector = new ExpandoObjectPropertyReflector(); PropertyReflectorFactory.DefaultPropertyReflector = new PropertyReflector(); PropertyReflectorFactory.DynamicObjectPropertyReflector = new DynamicObjectPropertyReflector(); }