Ejemplo n.º 1
0
        /// <summary>Creates a single TargetType object given a record string.</summary>
        /// <param name="text">Record string to deserialize.</param>
        /// <returns>Newly created TargetType object.</returns>
        /// <exception cref="ArgumentNullException">Thrown if text is null.</exception>
        /// <exception cref="TextSerializationException">Thrown if the number of fields in the record doesn't match that in TargetType.</exception>
        public TTargetType Deserialize(string text)
        {
            if (text == null)
            {
                throw new ArgumentNullException("text", "text cannot be null");
            }

            // Create the correct return objects depending on whether this is a value or reference type
            // This makes a difference for reflection later on when populating the fields dynamically.
            TTargetType returnObj    = new TTargetType();
            ValueType   returnStruct = null;

            if (_type.IsValueType)
            {
                object tempObj = returnObj;
                returnStruct = (ValueType)tempObj;
            }

            // Parse the record into it's individual fields depending on the type of serializer this is
            List <string> parseList     = Parse(text);
            int           requiredCount = _textFields.Values.Count(attr => !attr.Optional);

            if (parseList.Count < requiredCount || parseList.Count > _textFields.Count)
            {
                throw new TextSerializationException("TargetType field count doesn't match number of items in text");
            }

            // For each field that is parsed in the string, populate the correct corresponding field in the TargetType
            TextFieldAttribute[] attributes = _textFields.Values.ToArray();
            for (int i = 0; i < parseList.Count; i++)
            {
                TextFieldAttribute attr = attributes[i];
                if (attr != null)
                {
                    string strVal = Truncate(parseList[i], attr.Size);

                    // If there is a custom formatter, then use that to deserialize the string, otherwise use the default .NET behvavior.
                    object fieldObj = attr.Formatter != null?attr.Formatter.Deserialize(strVal) : Convert.ChangeType(strVal, attr.GetNativeType());

                    // Depending on whether the TargetType is a class or struct, you have to populate the fields differently
                    if (_type.IsValueType)
                    {
                        AssignToStruct(returnStruct, fieldObj, attr.Member);
                    }
                    else
                    {
                        AssignToClass(returnObj, fieldObj, attr.Member);
                    }
                }
            }

            // If this was a value type, need to do a little more magic so can be returned properly
            if (_type.IsValueType)
            {
                object tempObj = (object)returnStruct;
                returnObj = (TTargetType)tempObj;
            }

            return(returnObj);
        }
Ejemplo n.º 2
0
        protected TextSerializer()
        {
            // Get the Reflection type for the Generic Argument
            _type = GetType().GetGenericArguments()[0];

            // Double check that the TextSerializableAttribute has been attached to the TargetType
            object[] serAttrs = _type.GetCustomAttributes(typeof(TextSerializableAttribute), false);
            if (serAttrs.Length == 0)
            {
                throw new TextSerializationException("TargetType must have a TextSerializableAttribute attached");
            }

            // Get all the public properties and fields on the class
            MemberInfo[] members = _type.GetMembers(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField | BindingFlags.GetProperty);
            foreach (MemberInfo member in members)
            {
                // Check to see if they've marked up this field/property with the attribute for serialization
                object[] fieldAttrs = member.GetCustomAttributes(typeof(TextFieldAttribute), false);
                if (fieldAttrs.Length > 0)
                {
                    Type memberType;
                    if (member is FieldInfo)
                    {
                        memberType = ((FieldInfo)member).FieldType;
                    }
                    else if (member is PropertyInfo)
                    {
                        memberType = ((PropertyInfo)member).PropertyType;
                    }
                    else
                    {
                        throw new TextSerializationException("Invalid MemberInfo type encountered");
                    }

                    TextFieldAttribute textField = (TextFieldAttribute)fieldAttrs[0];

                    // Check for the AllowedValues Attribute and if it's there, store away the values into the other holder attribute
                    object[] allowedAttrs = member.GetCustomAttributes(typeof(AllowedValuesAttribute), false);
                    if (allowedAttrs.Length > 0)
                    {
                        AllowedValuesAttribute allowedAttr = (AllowedValuesAttribute)allowedAttrs[0];
                        textField.AllowedValues = allowedAttr.AllowedValues;
                    }

                    // If they don't override the name in the Attribute, use the MemberInfo name
                    if (string.IsNullOrEmpty(textField.Name))
                    {
                        textField.Name = member.Name;
                    }

                    textField.Member = member;
                    _textFields.Add(textField.Position, textField);
                }
            }
        }
Ejemplo n.º 3
0
        /// <summary>Serializes a single TargetType object into a properly formatted record string.</summary>
        /// <param name="obj">Object to serialize</param>
        /// <returns>Record string</returns>
        /// <exception cref="TextSerializationException">Thrown if an invalid class member is encountered.</exception>
        public string Serialize(TTargetType obj)
        {
            // First go through the object and get string representations of all the fields
            List <string> fieldList = new List <string>();

            for (int i = 0; i < _textFields.Count; i++)
            {
                TextFieldAttribute attr = _textFields[i];
                object             objValue;

                // Get the object from the field
                if (attr.Member is PropertyInfo)
                {
                    objValue = ((PropertyInfo)attr.Member).GetValue(obj, null);
                }
                else if (attr.Member is FieldInfo)
                {
                    objValue = ((FieldInfo)attr.Member).GetValue(obj);
                }
                else
                {
                    throw new TextSerializationException("Invalid MemberInfo type encountered");
                }

                // Get the string representation for the object.  If there is a custom formatter for this field, then
                // use that, otherwise use the default ToString behavior.
                string str = attr.Formatter != null?attr.Formatter.Serialize(objValue) : objValue.ToString();

                // Truncate the string if required
                fieldList.Add(Truncate(str, attr.Size));
            }

            // Now that all the strings are collected, put them together into a record string depending on the
            // type of serializer that this is.
            return(FormatOutput(fieldList));
        }