Exemplo n.º 1
0
        public static TEntity CloneFrom <TEntity>(
            this TEntity self,
            DynamicEntity source,
            bool overwrite = false,
            bool recursive = false,
            params DynamicPath[] ignore) where TEntity : DynamicEntity
        {
            var path = new DynamicPath();

            cloneFrom(self, source, overwrite, recursive, path, ignore);
            return(self);
        }
Exemplo n.º 2
0
        static void cloneFrom(DynamicEntity self, DynamicEntity source, bool overwrite, bool recursive, DynamicPath path, DynamicPath[] ignore)
        {
            var pairs = compileKeys(source).ToArray();

            foreach (var pair in pairs)
            {
                if (self.ContainsKey(pair.Key) && !overwrite)
                {
                    continue;
                }

                path.Push(pair.Key);
                if (ignore.Any(i => i.Equals(path)))
                {
                    goto next;
                }

                if (!tryGetValue(pair, out var value))
                {
                    continue;
                }

                if (value.IsCollectionOf <DynamicEntity>(out var items) && recursive)
                {
                    value = cloneDynamicBaseEntityCollection(pair.Key, items);
                    self.SetValue(pair.Key, value);
                    goto next;
                }

                if (!(value is DynamicEntity entity))
                {
                    self.SetValue(pair.Key, value);
                    goto next;
                }

                if (!recursive)
                {
                    goto next;
                }

                value = cloneDynamicEntity(entity, true, path, ignore);
                self.SetValue(pair.Key, value);

next:
                path.Pop();
            }

            bool tryGetValue(KeyValuePair <string, object> kvp, out object value)
            {
                value = null;
                if (kvp.Value is PropertyInfo property)
                {
                    if (!property.CanRead)
                    {
                        return(false);
                    }

                    value = property.GetValue(source, new object[0]);
                    return(true);
                }

                value = kvp.Value;
                return(true);
            }

            IEnumerable cloneDynamicBaseEntityCollection(string key, IEnumerable items)
            {
                Type type;
                var  prop = source.GetPropertyWithJsonPropertyName(key);

                if (prop is null)
                {
                    type = source[key].GetType();
                }
                else
                {
                    var implementedAs = prop.GetCustomAttribute <ImplementedAsAttribute>();
                    type = implementedAs != null ? implementedAs.Type : typeof(List <DynamicEntity>);
                }

                IList list;
                var   isArray = false;

                if (type.IsAssignableFrom(typeof(IList)))
                {
                    list = (IList)Activator.CreateInstance(type);
                }
                else if (typeof(Array).IsAssignableFrom(type))
                {
                    isArray = true;
                    list    = new List <DynamicEntity>();
                }
                else
                {
                    throw new NotImplementedException($"Cannot clone collection of type {type}");
                }

                foreach (DynamicEntity item in items)
                {
                    var cloned = item.Clone(item.GetType());
                    list.Add(cloned);
                }

                if (!isArray)
                {
                    return(list);
                }

                var array = new DynamicEntity[list.Count];
                var i     = 0;

                foreach (var item in list)
                {
                    array[i++] = (DynamicEntity)item;
                }
                return(array);
            }
        }
Exemplo n.º 3
0
        static DynamicEntity cloneDynamicEntity(DynamicEntity entity, bool recursive, DynamicPath path, DynamicPath[] ignore)
        {
            var type      = entity.GetType();
            var ctors     = type.GetConstructors();
            var emptyCtor = ctors.FirstOrDefault(c => c.GetParameters().Length == 0);

            if (emptyCtor == null)
            {
                throw new NotImplementedException("Consider looking up ctor with params matching properties names & types"); // todo
            }
            var cloned = (DynamicEntity)emptyCtor.Invoke(new object[0]);

            cloneFrom(cloned, entity, false, recursive, path, ignore);
            return(cloned);
        }
Exemplo n.º 4
0
 /// <summary>
 ///   Determines whether the specified value is equal to the current value.
 /// </summary>
 /// <param name="other">
 ///   A <see cref="DynamicPath"/> value to compare to this value.
 /// </param>
 /// <param name="stringComparison">
 ///   Specifies the string comparison strategy.
 /// </param>
 /// <returns>
 ///   <c>true</c> if <paramref name="other"/> is equal to the current value; otherwise <c>false</c>.
 /// </returns>
 public bool Equals(DynamicPath other, StringComparison stringComparison = StringComparison.InvariantCulture)
 {
     return(!(other is null) && string.Equals(StringValue, other.StringValue, stringComparison));
 }