コード例 #1
0
ファイル: CsvWriter.cs プロジェクト: cookcoder/CsvHelper
 /// <summary>
 /// Adds the members from the mapping. This will recursively
 /// traverse the mapping tree and add all members for
 /// reference maps.
 /// </summary>
 /// <param name="members">The members to be added to.</param>
 /// <param name="mapping">The mapping where the members are added from.</param>
 protected virtual void AddMembers(MemberMapCollection members, ClassMap mapping)
 {
     members.AddRange(mapping.MemberMaps);
     foreach (var refMap in mapping.ReferenceMaps)
     {
         AddMembers(members, refMap.Data.Mapping);
     }
 }
コード例 #2
0
ファイル: CsvWriter.cs プロジェクト: cookcoder/CsvHelper
        /// <summary>
        /// Writes the header record from the given members.
        /// </summary>
        /// <param name="type">The type of the record.</param>
        public virtual void WriteHeader(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

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

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

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

            if (type == typeof(object))
            {
                return;
            }

            if (context.WriterConfiguration.Maps[type] == null)
            {
                context.WriterConfiguration.Maps.Add(context.WriterConfiguration.AutoMap(type));
            }

            var members = new MemberMapCollection();

            AddMembers(members, context.WriterConfiguration.Maps[type]);

            foreach (var member in members)
            {
                if (CanWrite(member))
                {
                    if (member.Data.IndexEnd >= member.Data.Index)
                    {
                        var count = member.Data.IndexEnd - member.Data.Index + 1;
                        for (var i = 1; i <= count; i++)
                        {
                            WriteField(member.Data.Names.FirstOrDefault() + i);
                        }
                    }
                    else
                    {
                        WriteField(member.Data.Names.FirstOrDefault());
                    }
                }
            }

            context.HasHeaderBeenWritten = true;
        }
コード例 #3
0
        /// <inheritdoc/>
        public virtual void WriteHeader(Type type)
        {
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }

            if (type == typeof(object))
            {
                return;
            }

            if (context.Maps[type] == null)
            {
                context.Maps.Add(context.AutoMap(type));
            }

            var members = new MemberMapCollection();

            members.AddMembers(context.Maps[type]);

            var headerRecord = new List <string>();

            foreach (var member in members)
            {
                if (CanWrite(member))
                {
                    if (member.Data.IndexEnd >= member.Data.Index)
                    {
                        var count = member.Data.IndexEnd - member.Data.Index + 1;
                        for (var i = 1; i <= count; i++)
                        {
                            var header = member.Data.Names.FirstOrDefault() + i;
                            WriteField(header);
                            headerRecord.Add(header);
                        }
                    }
                    else
                    {
                        var header = member.Data.Names.FirstOrDefault();
                        WriteField(header);
                        headerRecord.Add(header);
                    }
                }
            }

            HeaderRecord = headerRecord.ToArray();

            hasHeaderBeenWritten = true;
        }
コード例 #4
0
ファイル: CsvWriter.cs プロジェクト: cookcoder/CsvHelper
        /// <summary>
        /// Creates the action for an object.
        /// </summary>
        /// <param name="type">The type of object to create the action for.</param>
        protected virtual Action <T> CreateActionForObject <T>(Type type)
        {
            var recordParameter          = Expression.Parameter(typeof(T), "record");
            var recordParameterConverted = Expression.Convert(recordParameter, type);

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

            AddMembers(members, context.WriterConfiguration.Maps[type]);

            if (members.Count == 0)
            {
                throw new WriterException(context, $"No properties are mapped for type '{type.FullName}'.");
            }

            var delegates = new List <Action <T> >();

            foreach (var memberMap in members)
            {
                if (memberMap.Data.WritingConvertExpression != null)
                {
                    // The user is providing the expression to do the conversion.
                    Expression exp = Expression.Invoke(memberMap.Data.WritingConvertExpression, recordParameterConverted);
                    exp = Expression.Call(Expression.Constant(this), nameof(WriteConvertedField), null, exp);
                    delegates.Add(Expression.Lambda <Action <T> >(exp, recordParameter).Compile());
                    continue;
                }

                if (!CanWrite(memberMap))
                {
                    continue;
                }

                Expression fieldExpression;

                if (memberMap.Data.IsConstantSet)
                {
                    if (memberMap.Data.Constant == null)
                    {
                        fieldExpression = Expression.Constant(string.Empty);
                    }
                    else
                    {
                        fieldExpression = Expression.Constant(memberMap.Data.Constant);
                        var typeConverterExpression = Expression.Constant(Configuration.TypeConverterFactory.GetConverter(memberMap.Data.Constant.GetType()));
                        var method = typeof(ITypeConverter).GetMethod(nameof(ITypeConverter.ConvertToString));
                        fieldExpression = Expression.Convert(fieldExpression, typeof(object));
                        fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression, Expression.Constant(this), Expression.Constant(memberMap.Data));
                    }
                }
                else
                {
                    if (memberMap.Data.TypeConverter == null)
                    {
                        // Skip if the type isn't convertible.
                        continue;
                    }

                    fieldExpression = CreateMemberExpression(recordParameterConverted, context.WriterConfiguration.Maps[type], memberMap);

                    var typeConverterExpression = Expression.Constant(memberMap.Data.TypeConverter);
                    memberMap.Data.TypeConverterOptions             = TypeConverterOptions.Merge(new TypeConverterOptions(), context.WriterConfiguration.TypeConverterOptionsFactory.GetOptions(memberMap.Data.Member.MemberType()), memberMap.Data.TypeConverterOptions);
                    memberMap.Data.TypeConverterOptions.CultureInfo = context.WriterConfiguration.CultureInfo;

                    var method = typeof(ITypeConverter).GetMethod(nameof(ITypeConverter.ConvertToString));
                    fieldExpression = Expression.Convert(fieldExpression, typeof(object));
                    fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression, Expression.Constant(this), Expression.Constant(memberMap.Data));

                    if (type.GetTypeInfo().IsClass)
                    {
                        var areEqualExpression = Expression.Equal(recordParameterConverted, Expression.Constant(null));
                        fieldExpression = Expression.Condition(areEqualExpression, Expression.Constant(string.Empty), fieldExpression);
                    }
                }

                var writeFieldMethodCall = Expression.Call(Expression.Constant(this), nameof(WriteConvertedField), null, fieldExpression);

                delegates.Add(Expression.Lambda <Action <T> >(writeFieldMethodCall, recordParameter).Compile());
            }

            var action = CombineDelegates(delegates);

            return(action);
        }
コード例 #5
0
        /// <summary>
        /// Creates a <see cref="Delegate"/> of type <see cref="Action{T}"/>
        /// that will write the given record using the current writer row.
        /// </summary>
        /// <typeparam name="T">The record type.</typeparam>
        /// <param name="record">The record.</param>
        protected override Action <T> CreateWriteDelegate <T>(T record)
        {
            var type = Writer.GetTypeForRecord(record);

            if (Writer.Context.Maps[type] == null)
            {
                Writer.Context.Maps.Add(Writer.Context.AutoMap(type));
            }

            var recordParameter          = Expression.Parameter(typeof(T), "record");
            var recordParameterConverted = Expression.Convert(recordParameter, type);

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

            members.AddMembers(Writer.Context.Maps[type]);

            if (members.Count == 0)
            {
                throw new WriterException(Writer.Context, $"No properties are mapped for type '{type.FullName}'.");
            }

            var delegates = new List <Action <T> >();

            foreach (var memberMap in members)
            {
                if (memberMap.Data.WritingConvertExpression != null)
                {
                    // The user is providing the expression to do the conversion.
                    var argsType          = typeof(ConvertToStringArgs <T>);
                    var newArgsExpression = Expression.New(argsType);
                    var fieldBinding      = Expression.Bind(argsType.GetProperty(nameof(ConvertToStringArgs <T> .Value)), recordParameterConverted);
                    var args = Expression.MemberInit(newArgsExpression, fieldBinding);

                    Expression exp = Expression.Invoke(memberMap.Data.WritingConvertExpression, args);
                    exp = Expression.Call(Expression.Constant(Writer), nameof(Writer.WriteField), null, exp);
                    delegates.Add(Expression.Lambda <Action <T> >(exp, recordParameter).Compile());
                    continue;
                }

                if (!Writer.CanWrite(memberMap))
                {
                    continue;
                }

                Expression fieldExpression;

                if (memberMap.Data.IsConstantSet)
                {
                    if (memberMap.Data.Constant == null)
                    {
                        fieldExpression = Expression.Constant(string.Empty);
                    }
                    else
                    {
                        fieldExpression = Expression.Constant(memberMap.Data.Constant);
                        var typeConverterExpression = Expression.Constant(Writer.Context.TypeConverterCache.GetConverter(memberMap.Data.Constant.GetType()));
                        var method = typeof(ITypeConverter).GetMethod(nameof(ITypeConverter.ConvertToString));
                        fieldExpression = Expression.Convert(fieldExpression, typeof(object));
                        fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression, Expression.Constant(Writer), Expression.Constant(memberMap.Data));
                    }
                }
                else
                {
                    if (memberMap.Data.TypeConverter == null)
                    {
                        // Skip if the type isn't convertible.
                        continue;
                    }

                    fieldExpression = ExpressionManager.CreateGetMemberExpression(recordParameterConverted, Writer.Context.Maps[type], memberMap);

                    var typeConverterExpression = Expression.Constant(memberMap.Data.TypeConverter);
                    memberMap.Data.TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions {
                        CultureInfo = Writer.Configuration.CultureInfo
                    }, Writer.Context.TypeConverterOptionsCache.GetOptions(memberMap.Data.Member.MemberType()), memberMap.Data.TypeConverterOptions);

                    var method = typeof(ITypeConverter).GetMethod(nameof(ITypeConverter.ConvertToString));
                    fieldExpression = Expression.Convert(fieldExpression, typeof(object));
                    fieldExpression = Expression.Call(typeConverterExpression, method, fieldExpression, Expression.Constant(Writer), Expression.Constant(memberMap.Data));

                    if (type.GetTypeInfo().IsClass)
                    {
                        var areEqualExpression = Expression.Equal(recordParameterConverted, Expression.Constant(null));
                        fieldExpression = Expression.Condition(areEqualExpression, Expression.Constant(string.Empty), fieldExpression);
                    }
                }

                var writeFieldMethodCall = Expression.Call(Expression.Constant(Writer), nameof(Writer.WriteConvertedField), null, fieldExpression, Expression.Constant(memberMap.Data.Type));

                delegates.Add(Expression.Lambda <Action <T> >(writeFieldMethodCall, recordParameter).Compile());
            }

            var action = CombineDelegates(delegates) ?? new Action <T>((T parameter) => { });

            return(action);
        }