Beispiel #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;
            }
        }
Beispiel #2
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;
            }
        }
Beispiel #3
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();
        }