예제 #1
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.IsArray &&
                type.GetArrayRank() == 1 &&
                type.HasElementType)
            {
                var elementType = type.GetElementType();

                if (elementType.CanShallowClone())
                {
                    var args = CloneArgs.Create(type, true);

                    var assign = Expression.Assign(
                        args.Target,
                        Expression.NewArrayBounds(elementType, Expression.Property(args.Source, "Length")));

                    var copy = Expression.Call(
                        args.Source,
                        _arrayCopy,
                        args.Target,
                        Expression.Constant(0));

                    args.CloneExpression = Expression.Block(
                        assign,
                        ExpressionHelper.RecordCopy(args.Context, args.Source, args.Target),
                        copy);

                    return(ExpressionHelper.Get <T>(args).Compile());
                }
            }

            return(null);
        }
예제 #2
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.IsGenericType() &&
                type.GetGenericTypeDefinition() == typeof(List <>) &&
                type.GetGenericArguments()[0].CanShallowClone())
            {
                var args = CloneArgs.Create(type, true);

                ConstructorInfo constructor = args
                                              .Type
                                              .GetConstructors()
                                              .Where(x =>
                                                     x.GetParameters().Length == 1 &&
                                                     x.GetParameters().ElementAt(0).ParameterType.IsGenericType())
                                              .FirstOrDefault();

                args.CloneExpression = Expression.Block(
                    Expression.Assign(args.Target, Expression.New(constructor, args.Source)),
                    ExpressionHelper.RecordCopy(args.Context, args.Source, args.Target));

                return(ExpressionHelper.Get <T>(args).Compile());
            }

            return(null);
        }
예제 #3
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.IsGenericType() &&
                (type.GetGenericTypeDefinition() == typeof(Tuple <>) ||
                 type.GetGenericTypeDefinition() == typeof(Tuple <,>) ||
                 type.GetGenericTypeDefinition() == typeof(Tuple <, ,>) ||
                 type.GetGenericTypeDefinition() == typeof(Tuple <, , ,>) ||
                 type.GetGenericTypeDefinition() == typeof(Tuple <, , , ,>) ||
                 type.GetGenericTypeDefinition() == typeof(Tuple <, , , , ,>) ||
                 type.GetGenericTypeDefinition() == typeof(Tuple <, , , , , ,>) ||
                 type.GetGenericTypeDefinition() == typeof(Tuple <, , , , , , ,>)))
            {
                var args = CloneArgs.Create(type, true);

                Type[] genericTypes = typeof(T).GetGenericArguments();
                var    cloneItems   = new Expression[genericTypes.Length];

                // Can't loop to 8, because instead of Item8 the last one is called Rest
                var loopCount = Math.Min(genericTypes.Length, 7);
                for (int i = 0; i < loopCount; i++)
                {
                    string itemName = "Item" + (i + 1).ToString(CultureInfo.InvariantCulture);

                    var itemType = genericTypes[i];

                    cloneItems[i] = itemType.CanShallowClone() ?
                                    Expression.Property(args.Source, itemName) :
                                    (Expression)ExpressionHelper.GetSafeClone(itemType, Expression.Property(args.Source, itemName), args.Context);
                }

                // add Rest expression if it's necessary
                if (genericTypes.Length == 8)
                {
                    string itemName = "Rest";

                    var itemType = genericTypes[7];

                    cloneItems[7] = itemType.CanShallowClone() ?
                                    Expression.Property(args.Source, itemName) :
                                    (Expression)ExpressionHelper.GetSafeClone(itemType, Expression.Property(args.Source, itemName), args.Context);
                }

                ConstructorInfo constructor   = args.Type.GetConstructors()[0];
                var             newExpression = Expression.New(constructor, cloneItems);

                args.CloneExpression = Expression.Block(
                    Expression.Assign(args.Target, newExpression),
                    ExpressionHelper.RecordCopy(args.Context, args.Source, args.Target));

                return(ExpressionHelper.Get <T>(args).Compile());
            }

            return(null);
        }
예제 #4
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.CanShallowClone())
            {
                var args = CloneArgs.Create(type, false);
                args.CloneExpression = Expression.Assign(args.Target, args.Source);
                return(ExpressionHelper.Get <T>(args).Compile());
            }

            return(null);
        }
예제 #5
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.IsNullable())
            {
                var structType = typeof(T).GetGenericArguments()[0];

                if (structType.CanShallowClone())
                {
                    var args = CloneArgs.Create(type, false);
                    args.CloneExpression = Expression.Assign(args.Target, args.Source);
                    return(ExpressionHelper.Get <T>(args).Compile());
                }
            }

            return(null);
        }
예제 #6
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.IsNullable())
            {
                var structType = typeof(T).GetGenericArguments()[0];

                if (!structType.CanShallowClone())
                {
                    var args           = CloneArgs.Create(type, false);
                    var sourceProperty = Expression.Property(args.Source, "Value");
                    var cloneCall      = ExpressionHelper.GetUnSafeClone(structType, sourceProperty, args.Context);
                    var newNullable    = Expression.New(typeof(T).GetConstructor(new[] { structType }), cloneCall);
                    args.CloneExpression = Expression.Assign(args.Target, newNullable);
                    return(ExpressionHelper.Get <T>(args).Compile());
                }
            }

            return(null);
        }
예제 #7
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.IsClass() &&
                !type.IsArray &&
                !type.IsAnonymous())
            {
                if (type.HasDefaultConstructor() ||
                    CloneConfig <T> .Initializer != null)
                {
                    var args = CloneArgs.Create(type, true);

                    Expression createExpression = CloneConfig <T> .Initializer != null?
                                                  Expression.Invoke(Expression.Constant(CloneConfig <T> .Initializer), args.Source) :
                                                      (Expression)Expression.New(args.Type);

                    List <Expression> expressions = new List <Expression>()
                    {
                        Expression.Assign(args.Target, createExpression),
                        ExpressionHelper.RecordCopy(args.Context, args.Source, args.Target),
                        ExpressionHelper.GetMemberAssignments <T>(args.Source, args.Target, args.Context),
                        ExpressionHelper.GetCollectionAssignment <T>(args.Source, args.Target, args.Context)
                    };

                    args.CloneExpression = Expression.Block(expressions.Where(x => x != null));

                    return(ExpressionHelper.Get <T>(args).Compile());
                }
                else
                {
                    return((source, context) =>
                    {
                        throw new ArgumentException($"({type}) has no default constructor or registered initializer.");
                    });
                }
            }

            return(null);
        }
예제 #8
0
        public CloneDel <T> Create <T>()
        {
            var type = typeof(T);

            if (type.IsGenericType() &&
                type.GetGenericTypeDefinition() == typeof(KeyValuePair <,>))
            {
                var args = CloneArgs.Create(type, false);

                var keyType   = args.Type.GetGenericArguments()[0];
                var valueType = args.Type.GetGenericArguments()[1];

                ConstructorInfo _constructor = args
                                               .Type
                                               .GetConstructors()
                                               .Where(x => x.GetParameters().Length == 2)
                                               .FirstOrDefault();

                Expression cloneKey = keyType.CanShallowClone() ?
                                      Expression.Property(args.Source, "Key") :
                                      (Expression)ExpressionHelper.GetSafeClone(keyType, Expression.Property(args.Source, "Key"), args.Context);

                Expression cloneValue = valueType.CanShallowClone() ?
                                        Expression.Property(args.Source, "Value") :
                                        (Expression)ExpressionHelper.GetSafeClone(valueType, Expression.Property(args.Source, "Value"), args.Context);

                var newExpression = Expression.New(
                    _constructor,
                    cloneKey,
                    cloneValue);

                args.CloneExpression = Expression.Assign(args.Target, newExpression);

                return(ExpressionHelper.Get <T>(args).Compile());
            }

            return(null);
        }