Exemplo n.º 1
0
        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;
        }
Exemplo n.º 2
0
        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);
        }
Exemplo n.º 3
0
            /// <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);
            }
Exemplo n.º 4
0
 public TypeAliasWalker(IPropertyReflector propertyReflector)
     : base(propertyReflector)
 {
     this.ReflectBaseTypes  = true;
     this.ReflectInterfaces = true;
     this.ReflectProperties = false;
 }
Exemplo n.º 5
0
        /// <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;
        }
Exemplo n.º 6
0
        /// <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);
        }
Exemplo n.º 7
0
        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;
        }
Exemplo n.º 8
0
        /// <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);
            }
Exemplo n.º 9
0
 public PropertyInspector(IPropertyReflector reflector)
 {
     _reflector = reflector;
 }
Exemplo n.º 10
0
        /// <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);
        }
Exemplo n.º 11
0
        /// <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);
        }
Exemplo n.º 12
0
        /// <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));
            }
        }
Exemplo n.º 13
0
 /// <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))
 {
 }
Exemplo n.º 14
0
 public PropertyInspector([NotNull] IPropertyReflector reflector)
 {
     _reflector = reflector ?? throw new ArgumentNullException(nameof(reflector));
 }
Exemplo n.º 15
0
 /// <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)
 {
 }
Exemplo n.º 16
0
 static PropertyReflectorFactory()
 {
     PropertyReflectorFactory.ExpandoObjectPropertyReflector = new ExpandoObjectPropertyReflector();
     PropertyReflectorFactory.DefaultPropertyReflector       = new PropertyReflector();
     PropertyReflectorFactory.DynamicObjectPropertyReflector = new DynamicObjectPropertyReflector();
 }