Esempio n. 1
0
        /// <summary>
        /// Writes the header record from the given properties.
        /// </summary>
        /// <param name="type">The type of the record.</param>
        protected virtual void WriteHeader(Type type)
        {
            if (configuration.Properties.Count == 0)
            {
                configuration.AttributeMapping(type);
            }

            var properties = new CsvPropertyMapCollection();

            properties.AddRange(configuration.Properties);
            foreach (var reference in configuration.References)
            {
                properties.AddRange(reference.ReferenceProperties);
            }

            foreach (var property in properties)
            {
                if (!property.IgnoreValue)
                {
                    WriteField(property.NameValue);
                }
            }
            NextRecord();
            hasHeaderBeenWritten = true;
        }
Esempio n. 2
0
        /// <summary>
        /// Writes the header record from the given properties.
        /// </summary>
        /// <param name="type">The type of the record.</param>
        public virtual void WriteHeader(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            if (!configuration.HasHeaderRecord)
            {
                throw new CsvWriterException("Configuration.HasHeaderRecord is false. This will need to be enabled to write the header.");
            }

            if (hasHeaderBeenWritten)
            {
                throw new CsvWriterException("The header record has already been written. You can't write it more than once.");
            }

            if (hasRecordBeenWritten)
            {
                throw new CsvWriterException("Records have already been written. You can't write the header after writing records has started.");
            }

            if (configuration.Properties.Count == 0)
            {
                configuration.AttributeMapping(type);
            }

            var properties = new CsvPropertyMapCollection();

            properties.AddRange(configuration.Properties);
            foreach (var reference in configuration.References)
            {
                properties.AddRange(reference.ReferenceProperties);
            }

            foreach (var property in properties)
            {
                if (!property.IgnoreValue)
                {
                    WriteField(property.NameValue);
                }
            }

            NextRecord();

            hasHeaderBeenWritten = true;
        }
Esempio n. 3
0
 /// <summary>
 /// Adds the properties from the mapping. This will recursively
 /// traverse the mapping tree and add all properties for
 /// reference maps.
 /// </summary>
 /// <param name="properties">The properties to be added to.</param>
 /// <param name="mapping">The mapping where the properties are added from.</param>
 protected virtual void AddProperties(CsvPropertyMapCollection properties, CsvClassMap mapping)
 {
     properties.AddRange(mapping.PropertyMaps);
     foreach (var refMap in mapping.ReferenceMaps)
     {
         AddProperties(properties, refMap.Mapping);
     }
 }
Esempio n. 4
0
        /// <summary>
        /// Creates the write record action for the given type if it
        /// doesn't already exist.
        /// </summary>
        /// <param name="type">The type of the custom class being written.</param>
        /// <param name="expressionCompiler">The expression compiler.</param>
        protected virtual void CreateWriteRecordAction(Type type, Func <Expression, ParameterExpression, ParameterExpression, Delegate> expressionCompiler)
        {
            if (typeActions.ContainsKey(type))
            {
                return;
            }

            var writerParameter = Expression.Parameter(typeof(ICsvWriter), "writer");
            var recordParameter = Expression.Parameter(type, "record");

            if (configuration.Properties.Count == 0)
            {
                configuration.AttributeMapping(type);
            }

            // Get a list of all the properties so they will
            // be sorted properly.
            var properties = new CsvPropertyMapCollection();

            properties.AddRange(configuration.Properties);
            foreach (var reference in configuration.References)
            {
                properties.AddRange(reference.ReferenceProperties);
            }

            // A list of expressions that will go inside
            // the lambda code block.
            var expressions = new List <Expression>();

            foreach (var propertyMap in properties)
            {
                if (propertyMap.IgnoreValue)
                {
                    // Skip ignored properties.
                    continue;
                }

                if (string.IsNullOrEmpty(propertyMap.FormatValue) && (propertyMap.TypeConverterValue == null || !propertyMap.TypeConverterValue.CanConvertTo(typeof(string))))
                {
                    // Skip if the type isn't convertible.
                    continue;
                }

                // So we don't have to access a modified closure.
                var propertyMapCopy = propertyMap;

                // Get the reference this property is a part of.
                var reference = (from r in configuration.References
                                 from p in r.ReferenceProperties
                                 where p == propertyMapCopy
                                 select r).SingleOrDefault();

                // Get the current object. Either the param passed in
                // or a reference property object.
                var currentRecordObject =
                    reference == null
                                                ? (Expression)recordParameter
                                                : Expression.Property(recordParameter, reference.Property);

                Expression fieldExpression = Expression.Property(currentRecordObject, propertyMap.PropertyValue);

                if (!string.IsNullOrEmpty(propertyMap.FormatValue))
                {
                    // Use string.Format instead of TypeConverter.
                    var formatExpression = Expression.Constant(propertyMap.FormatValue);
                    //MethodInfo method;
                    if (configuration.UseInvariantCulture)
                    {
                        var method = typeof(string).GetMethod("Format", new[] { typeof(IFormatProvider), typeof(string), typeof(object) });
                        fieldExpression = Expression.Convert(fieldExpression, typeof(object));
                        fieldExpression = Expression.Call(method, Expression.Constant(CultureInfo.InvariantCulture), formatExpression, fieldExpression);
                    }
                    else
                    {
                        var method = typeof(string).GetMethod("Format", new[] { typeof(string), typeof(object) });
                        fieldExpression = Expression.Convert(fieldExpression, typeof(object));
                        fieldExpression = Expression.Call(method, formatExpression, fieldExpression);
                    }
                }
                else
                {
                    var typeConverterExpression = Expression.Constant(propertyMap.TypeConverterValue);
                    var convertMethod           = Configuration.UseInvariantCulture ? "ConvertToInvariantString" : "ConvertToString";
                    var method = propertyMap.TypeConverterValue.GetType().GetMethod(convertMethod, new[] { typeof(object) });

                    fieldExpression = Expression.Convert(fieldExpression, typeof(object));

                    fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression);
                }

                var areEqualExpression = Expression.Equal(currentRecordObject, Expression.Constant(null));
                fieldExpression = Expression.Condition(areEqualExpression, Expression.Constant(string.Empty), fieldExpression);

                var writeFieldMethodCall = Expression.Call(writerParameter, "WriteField", new[] { typeof(string) }, fieldExpression);
                expressions.Add(writeFieldMethodCall);
            }

            var body = Expression.Block(expressions);
            var func = expressionCompiler(body, writerParameter, recordParameter);

            typeActions[type] = func;
        }
Esempio n. 5
0
        /// <summary>
        /// Gets the action delegate used to write the custom
        /// class object to the writer.
        /// </summary>
        /// <typeparam name="T">The type of the custom class being written.</typeparam>
        /// <returns>The action delegate.</returns>
        protected virtual Action <CsvWriter, T> GetWriteRecordAction <T>() where T : class
        {
            var type = typeof(T);

            if (!typeActions.ContainsKey(type))
            {
                Action <CsvWriter, T> func = null;
                var writerParameter        = Expression.Parameter(typeof(CsvWriter), "writer");
                var recordParameter        = Expression.Parameter(typeof(T), "record");

                if (configuration.Properties.Count == 0)
                {
                    configuration.AttributeMapping <T>();
                }

                // Get a list of all the properties so they will
                // be sorted properly.
                var properties = new CsvPropertyMapCollection();
                properties.AddRange(configuration.Properties);
                foreach (var reference in configuration.References)
                {
                    properties.AddRange(reference.ReferenceProperties);
                }

                // A list of expressions that will go inside
                // the lambda code block.
                var expressions = new List <Expression>();

                foreach (var propertyMap in properties)
                {
                    if (propertyMap.IgnoreValue)
                    {
                        // Skip ignored properties.
                        continue;
                    }

                    if (propertyMap.TypeConverterValue == null || !propertyMap.TypeConverterValue.CanConvertTo(typeof(string)))
                    {
                        // Skip if the type isn't convertible.
                        continue;
                    }

                    // So we don't have to access a modified closure.
                    var propertyMapCopy = propertyMap;

                    // Get the reference this property is a part of.
                    var reference = (from r in configuration.References
                                     from p in r.ReferenceProperties
                                     where p == propertyMapCopy
                                     select r).SingleOrDefault();

                    // Get the current object. Either the param passed in
                    // or a reference property object.
                    var currentRecordObject =
                        reference == null
                                                        ? (Expression)recordParameter
                                                        : Expression.Property(recordParameter, reference.Property);

                    Expression fieldExpression         = Expression.Property(currentRecordObject, propertyMap.PropertyValue);
                    var        typeConverterExpression = Expression.Constant(propertyMap.TypeConverterValue);
                    var        convertMethod           = Configuration.UseInvariantCulture ? "ConvertToInvariantString" : "ConvertToString";
                    var        method = propertyMap.TypeConverterValue.GetType().GetMethod(convertMethod, new[] { typeof(object) });
                    fieldExpression = Expression.Convert(fieldExpression, typeof(object));
                    fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression);

                    var areEqualExpression = Expression.Equal(currentRecordObject, Expression.Constant(null));
                    fieldExpression = Expression.Condition(areEqualExpression, Expression.Constant(string.Empty), fieldExpression);

                    var writeFieldMethodCall = Expression.Call(writerParameter, "WriteField", new[] { typeof(string) }, fieldExpression);
                    expressions.Add(writeFieldMethodCall);
                }

                var body = Expression.Block(expressions);
                func = Expression.Lambda <Action <CsvWriter, T> >(body, writerParameter, recordParameter).Compile();

                typeActions[type] = func;
            }

            return((Action <CsvWriter, T>)typeActions[type]);
        }