예제 #1
0
        /// <summary>
        /// Creates a new CloneType based on a <see cref="System.Type"/>, gathering all the information that is necessary for cloning.
        /// </summary>
        /// <param name="type"></param>
        public CloneType(Type type)
        {
            this.type         = type.GetTypeInfo();
            this.plainOldData =
                this.type.IsPlainOldData() ||
                typeof(MemberInfo).GetTypeInfo().IsAssignableFrom(this.type);                 /* Handle MemberInfo like POD */
            this.investigateOwnership = !this.plainOldData;
            this.surrogate            = CloneProvider.GetSurrogateFor(this.type);
            if (this.type.IsArray)
            {
                if (this.type.GetArrayRank() > 1)
                {
                    throw new NotSupportedException(
                              "Cloning multidimensional arrays is not supported in Duality. " +
                              "Consider skipping the referring field via [CloneField] or [DontSerialize] " +
                              "attribute, or use a regular array instead.");
                }
                this.elementType = CloneProvider.GetCloneType(this.type.GetElementType());
            }

            CloneBehaviorAttribute defaultBehaviorAttrib = CloneProvider.GetCloneBehaviorAttribute(this.type);

            if (defaultBehaviorAttrib != null && defaultBehaviorAttrib.Behavior != CloneBehavior.Default)
            {
                this.behavior = defaultBehaviorAttrib.Behavior;
            }
            else
            {
                this.behavior = CloneBehavior.ChildObject;
            }
        }
예제 #2
0
        internal static CloneBehaviorAttribute GetCloneBehaviorAttribute(Type type)
        {
            // Assembly-level attributes pointing to this Type
            if (globalCloneBehavior == null)
            {
                globalCloneBehavior = ReflectionHelper.GetCustomAssemblyAttributes <CloneBehaviorAttribute>().ToArray();
            }
            for (int i = 0; i < globalCloneBehavior.Length; i++)
            {
                CloneBehaviorAttribute globalAttrib = globalCloneBehavior[i];
                if (globalAttrib.TargetType.IsAssignableFrom(type))
                {
                    return(globalAttrib);
                }
            }

            // Attributes attached directly to this Type
            CloneBehaviorAttribute directAttrib;

            if (!cloneBehaviorCache.TryGetValue(type, out directAttrib))
            {
                directAttrib             = type.GetCustomAttributes <CloneBehaviorAttribute>().FirstOrDefault();
                cloneBehaviorCache[type] = directAttrib;
            }
            return(directAttrib);
        }
예제 #3
0
 public CloneField(FieldInfo field, CloneType typeInfo, CloneFieldFlags flags, CloneBehaviorAttribute behavior, bool isAlwaysReference)
 {
     this.field             = field;
     this.typeInfo          = typeInfo;
     this.flags             = flags;
     this.behavior          = behavior;
     this.isAlwaysReference = isAlwaysReference;
 }
예제 #4
0
파일: CloneType.cs 프로젝트: undue/duality
			public CloneField(FieldInfo field, CloneType typeInfo, CloneFieldFlags flags, CloneBehaviorAttribute behavior, bool isAlwaysReference)
			{
				this.field = field;
				this.typeInfo = typeInfo;
				this.flags = flags;
				this.behavior = behavior;
				this.isAlwaysReference = isAlwaysReference;
			}
예제 #5
0
        /// <summary>
        /// Creates a new CloneType based on a <see cref="System.Type"/>, gathering all the information that is necessary for cloning.
        /// </summary>
        /// <param name="type"></param>
        public CloneType(Type type)
        {
            this.type         = type;
            this.plainOldData =
                this.type.IsPlainOldData() ||
                typeof(MemberInfo).IsAssignableFrom(this.type);                 /* Handle MemberInfo like POD */
            this.investigateOwnership = !this.plainOldData;
            this.surrogate            = CloneProvider.GetSurrogateFor(this.type);
            if (this.type.IsArray)
            {
                this.elementType = CloneProvider.GetCloneType(this.type.GetElementType());
            }

            CloneBehaviorAttribute defaultBehaviorAttrib = CloneProvider.GetCloneBehaviorAttribute(this.type);

            if (defaultBehaviorAttrib != null && defaultBehaviorAttrib.Behavior != CloneBehavior.Default)
            {
                this.behavior = defaultBehaviorAttrib.Behavior;
            }
            else
            {
                this.behavior = CloneBehavior.ChildObject;
            }
        }
예제 #6
0
        private List <Expression> CreateSetupFuncContent(Expression setup, Expression source, Expression target)
        {
            List <Expression> mainBlock = new List <Expression>();
            bool anyContent             = false;

            for (int i = 0; i < this.fieldData.Length; i++)
            {
                // Don't need to scan "plain old data" and reference fields
                if (this.fieldData[i].FieldType.IsPlainOldData)
                {
                    continue;
                }
                if (this.fieldData[i].IsAlwaysReference)
                {
                    continue;
                }
                if (this.fieldData[i].FieldType.Type.IsValueType && !this.fieldData[i].FieldType.InvestigateOwnership)
                {
                    continue;
                }
                anyContent = true;

                // Call HandleObject on the fields value
                CloneBehaviorAttribute behaviorAttribute = this.fieldData[i].Behavior;
                FieldInfo  field = this.fieldData[i].Field;
                Expression handleObjectExpression;
                if (this.fieldData[i].FieldType.Type.IsValueType)
                {
                    if (behaviorAttribute == null)
                    {
                        handleObjectExpression = Expression.Call(setup,
                                                                 SetupHandleValue.MakeGenericMethod(field.FieldType),
                                                                 Expression.Field(source, field),
                                                                 Expression.Field(target, field),
                                                                 Expression.Constant(CloneBehavior.Default),
                                                                 Expression.Constant(null, typeof(TypeInfo)));
                    }
                    else
                    {
                        handleObjectExpression = Expression.Call(setup,
                                                                 SetupHandleValue.MakeGenericMethod(field.FieldType),
                                                                 Expression.Field(source, field),
                                                                 Expression.Field(target, field),
                                                                 Expression.Constant(behaviorAttribute.Behavior),
                                                                 Expression.Constant(behaviorAttribute.TargetType));
                    }
                }
                else
                {
                    if (behaviorAttribute == null)
                    {
                        handleObjectExpression = Expression.Call(setup,
                                                                 SetupHandleObject.MakeGenericMethod(field.FieldType),
                                                                 Expression.Field(source, field),
                                                                 Expression.Field(target, field),
                                                                 Expression.Constant(CloneBehavior.Default),
                                                                 Expression.Constant(null, typeof(TypeInfo)));
                    }
                    else if (behaviorAttribute.TargetType == null || field.FieldType.GetTypeInfo().IsAssignableFrom(behaviorAttribute.TargetType.GetTypeInfo()))
                    {
                        handleObjectExpression = Expression.Call(setup,
                                                                 SetupHandleObject.MakeGenericMethod(field.FieldType),
                                                                 Expression.Field(source, field),
                                                                 Expression.Field(target, field),
                                                                 Expression.Constant(behaviorAttribute.Behavior),
                                                                 Expression.Constant(null, typeof(TypeInfo)));
                    }
                    else
                    {
                        handleObjectExpression = Expression.Call(setup,
                                                                 SetupHandleObject.MakeGenericMethod(field.FieldType),
                                                                 Expression.Field(source, field),
                                                                 Expression.Field(target, field),
                                                                 Expression.Constant(behaviorAttribute.Behavior),
                                                                 Expression.Constant(behaviorAttribute.TargetType));
                    }
                }
                mainBlock.Add(handleObjectExpression);
            }
            if (!anyContent)
            {
                return(null);
            }
            return(mainBlock);
        }
예제 #7
0
        public void Init()
        {
            if (this.surrogate != null)
            {
                return;
            }
            if (this.plainOldData)
            {
                return;
            }

            if (this.type.IsArray)
            {
                this.investigateOwnership = !(this.elementType.IsPlainOldData || (this.elementType.Type.IsValueType && !this.elementType.InvestigateOwnership));
                return;
            }
            else
            {
                this.investigateOwnership = typeof(ICloneExplicit).GetTypeInfo().IsAssignableFrom(this.type) || this.surrogate != null;
            }

            // Retrieve field data
            List <CloneField> fieldData = new List <CloneField>();

            foreach (FieldInfo field in this.type.DeclaredFieldsDeep())
            {
                if (field.IsStatic)
                {
                    continue;
                }
                if (field.IsInitOnly)
                {
                    continue;
                }
                if (field.HasAttributeCached <ManuallyClonedAttribute>())
                {
                    continue;
                }
                if (field.DeclaringType.GetTypeInfo().HasAttributeCached <ManuallyClonedAttribute>())
                {
                    continue;
                }

                CloneFieldFlags     flags       = CloneFieldFlags.None;
                CloneFieldAttribute fieldAttrib = field.GetAttributesCached <CloneFieldAttribute>().FirstOrDefault();
                if (fieldAttrib != null)
                {
                    flags = fieldAttrib.Flags;
                }

                if (field.HasAttributeCached <DontSerializeAttribute>() && !flags.HasFlag(CloneFieldFlags.DontSkip))
                {
                    continue;
                }
                if (flags.HasFlag(CloneFieldFlags.Skip))
                {
                    continue;
                }

                CloneBehaviorAttribute behaviorAttrib = field.GetAttributesCached <CloneBehaviorAttribute>().FirstOrDefault();
                CloneType fieldType         = CloneProvider.GetCloneType(field.FieldType);
                bool      isAlwaysReference =
                    (behaviorAttrib != null) &&
                    (behaviorAttrib.TargetType == null || field.FieldType.GetTypeInfo().IsAssignableFrom(behaviorAttrib.TargetType.GetTypeInfo())) &&
                    (behaviorAttrib.Behavior == CloneBehavior.Reference);

                // Can this field own any objects itself?
                if (!this.investigateOwnership)
                {
                    bool fieldCanOwnObjects = true;
                    if (fieldType.IsPlainOldData)
                    {
                        fieldCanOwnObjects = false;
                    }
                    if (isAlwaysReference)
                    {
                        fieldCanOwnObjects = false;
                    }
                    if (fieldType.Type.IsValueType && !fieldType.InvestigateOwnership)
                    {
                        fieldCanOwnObjects = false;
                    }

                    if (fieldCanOwnObjects)
                    {
                        this.investigateOwnership = true;
                    }
                }

                CloneField fieldEntry = new CloneField(field, fieldType, flags, behaviorAttrib, isAlwaysReference);
                fieldData.Add(fieldEntry);
            }
            this.fieldData = fieldData.ToArray();

            // Build precompile functions for setup and (partially) assignment
            this.CompileAssignmentFunc();
            this.CompileSetupFunc();
            this.CompileValueAssignmentFunc();
            this.CompileValueSetupFunc();
        }