Exemple #1
0
        /// <summary>
        /// Creates the constructor arguments used to create a type.
        /// </summary>
        /// <param name="map">The mapping to create the arguments for.</param>
        /// <param name="argumentExpressions">The arguments that will be added to the mapping.</param>
        protected virtual void CreateConstructorArgumentExpressionsForMapping(ClassMap map, List <Expression> argumentExpressions)
        {
            foreach (var parameterMap in map.ParameterMaps)
            {
                if (parameterMap.ConstructorTypeMap != null)
                {
                    // Constructor paramter type.
                    var arguments = new List <Expression>();
                    CreateConstructorArgumentExpressionsForMapping(parameterMap.ConstructorTypeMap, arguments);
                    var constructorExpression = Expression.New(Reader.Configuration.GetConstructor(parameterMap.ConstructorTypeMap.ClassType), arguments);

                    argumentExpressions.Add(constructorExpression);
                }
                else if (parameterMap.ReferenceMap != null)
                {
                    // Reference type.

                    var referenceBindings = new List <MemberBinding>();
                    ExpressionManager.CreateMemberBindingsForMapping(parameterMap.ReferenceMap.Data.Mapping, parameterMap.ReferenceMap.Data.Parameter.ParameterType, referenceBindings);

                    // This is in case an IContractResolver is being used.
                    var type          = ReflectionHelper.CreateInstance(parameterMap.ReferenceMap.Data.Parameter.ParameterType).GetType();
                    var referenceBody = Expression.MemberInit(Expression.New(type), referenceBindings);

                    argumentExpressions.Add(referenceBody);
                }
                else
                {
                    // Value type.

                    var index = Reader.Configuration.HasHeaderRecord
                                                ? Reader.GetFieldIndex(parameterMap.Data.Name, 0)
                                                : parameterMap.Data.Index;

                    // Get the field using the field index.
                    var        method          = typeof(IReaderRow).GetProperty("Item", typeof(string), new[] { typeof(int) }).GetGetMethod();
                    Expression fieldExpression = Expression.Call(Expression.Constant(Reader), method, Expression.Constant(index, typeof(int)));

                    // Convert the field.
                    var typeConverterExpression = Expression.Constant(parameterMap.Data.TypeConverter);
                    parameterMap.Data.TypeConverterOptions             = TypeConverterOptions.Merge(new TypeConverterOptions(), Reader.context.ReaderConfiguration.TypeConverterOptionsFactory.GetOptions(parameterMap.Data.Parameter.ParameterType), parameterMap.Data.TypeConverterOptions);
                    parameterMap.Data.TypeConverterOptions.CultureInfo = Reader.context.ReaderConfiguration.CultureInfo;

                    // Create type converter expression.
                    var memberMapData = new MemberMapData(null)
                    {
                        Index                = parameterMap.Data.Index,
                        TypeConverter        = parameterMap.Data.TypeConverter,
                        TypeConverterOptions = parameterMap.Data.TypeConverterOptions
                    };
                    memberMapData.Names.Add(parameterMap.Data.Name);
                    Expression typeConverterFieldExpression = Expression.Call(typeConverterExpression, nameof(ITypeConverter.ConvertFromString), null, fieldExpression, Expression.Constant(Reader), Expression.Constant(memberMapData));
                    typeConverterFieldExpression = Expression.Convert(typeConverterFieldExpression, parameterMap.Data.Parameter.ParameterType);

                    fieldExpression = typeConverterFieldExpression;

                    argumentExpressions.Add(fieldExpression);
                }
            }
        }
Exemple #2
0
        /// <summary>
        /// Creates a <see cref="Delegate"/> of type <see cref="Func{T}"/>
        /// that will create a record of the given type using the current
        /// reader row.
        /// </summary>
        /// <param name="recordType">The record type.</param>
        protected override Delegate CreateCreateRecordDelegate(Type recordType)
        {
            if (Reader.context.ReaderConfiguration.Maps[recordType] == null)
            {
                Reader.context.ReaderConfiguration.Maps.Add(Reader.context.ReaderConfiguration.AutoMap(recordType));
            }

            var map = Reader.context.ReaderConfiguration.Maps[recordType];

            Expression body;

            if (map.ParameterMaps.Count > 0)
            {
                // This is a constructor paramter type.
                var arguments = new List <Expression>();
                CreateConstructorArgumentExpressionsForMapping(map, arguments);

                body = Expression.New(Reader.Configuration.GetConstructor(map.ClassType), arguments);
            }
            else
            {
                var bindings = new List <MemberBinding>();
                ExpressionManager.CreateMemberBindingsForMapping(map, recordType, bindings);

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

                if (map.Constructor is NewExpression)
                {
                    body = Expression.MemberInit((NewExpression)map.Constructor, bindings);
                }
                else if (map.Constructor is MemberInitExpression)
                {
                    var memberInitExpression = (MemberInitExpression)map.Constructor;
                    var defaultBindings      = memberInitExpression.Bindings.ToList();
                    defaultBindings.AddRange(bindings);
                    body = Expression.MemberInit(memberInitExpression.NewExpression, defaultBindings);
                }
                else
                {
                    // This is in case an IContractResolver is being used.
                    var type = ReflectionHelper.CreateInstance(recordType).GetType();
                    body = Expression.MemberInit(Expression.New(type), bindings);
                }
            }

            var funcType = typeof(Func <>).MakeGenericType(recordType);

            return(Expression.Lambda(funcType, body).Compile());
        }
        /// <summary>
        /// Creates a <see cref="Delegate"/> of type <see cref="Func{T}"/>
        /// that will create a record of the given type using the current
        /// reader row.
        /// </summary>
        /// <param name="recordType">The record type.</param>
        protected override Delegate CreateCreateRecordDelegate(Type recordType)
        {
            if (Reader.Context.Maps[recordType] == null)
            {
                Reader.Context.Maps.Add(Reader.Context.AutoMap(recordType));
            }

            var map = Reader.Context.Maps[recordType];

            Expression body;

            if (map.ParameterMaps.Count > 0)
            {
                // This is a constructor parameter type.
                var arguments = new List <Expression>();
                ExpressionManager.CreateConstructorArgumentExpressionsForMapping(map, arguments);

                var args = new GetConstructorArgs
                {
                    ClassType = map.ClassType
                };

                body = Expression.New(Reader.Configuration.GetConstructor(args), arguments);
            }
            else
            {
                var assignments = new List <MemberAssignment>();
                ExpressionManager.CreateMemberAssignmentsForMapping(map, assignments);

                if (assignments.Count == 0)
                {
                    throw new ReaderException(Reader.Context, $"No members are mapped for type '{recordType.FullName}'.");
                }

                body = ExpressionManager.CreateInstanceAndAssignMembers(recordType, assignments);
            }

            var funcType = typeof(Func <>).MakeGenericType(recordType);

            return(Expression.Lambda(funcType, body).Compile());
        }
Exemple #4
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.WriterConfiguration.Maps[type] == null)
            {
                Writer.Context.WriterConfiguration.Maps.Add(Writer.Context.WriterConfiguration.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.WriterConfiguration.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.
                    Expression exp = Expression.Invoke(memberMap.Data.WritingConvertExpression, recordParameterConverted);
                    exp = Expression.Call(Expression.Constant(Writer), nameof(Writer.WriteConvertedField), 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.Configuration.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.WriterConfiguration.Maps[type], memberMap);

                    var typeConverterExpression = Expression.Constant(memberMap.Data.TypeConverter);
                    memberMap.Data.TypeConverterOptions = TypeConverterOptions.Merge(new TypeConverterOptions {
                        CultureInfo = Writer.Context.WriterConfiguration.CultureInfo
                    }, Writer.Context.WriterConfiguration.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);

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

            var action = CombineDelegates(delegates);

            return(action);
        }
Exemple #5
0
 /// <summary>
 /// Creates a new instance using the given reader.
 /// </summary>
 /// <param name="reader">The reader.</param>
 public RecordHydrator(CsvReader reader)
 {
     this.reader       = reader;
     expressionManager = new ExpressionManager(reader);
 }
Exemple #6
0
 /// <summary>
 /// Initializes a new instance using the given writer.
 /// </summary>
 /// <param name="writer">The writer.</param>
 public RecordWriter(CsvWriter writer)
 {
     Writer            = writer;
     ExpressionManager = new ExpressionManager(writer);
 }
Exemple #7
0
 /// <summary>
 /// Initializes a new instance using the given writer.
 /// </summary>
 /// <param name="writer">The writer.</param>
 public RecordWriter(CsvWriter writer)
 {
     Writer            = writer;
     ExpressionManager = ObjectResolver.Current.Resolve <ExpressionManager>(writer);
 }
Exemple #8
0
 /// <summary>
 /// Initializes a new instance using the given reader.
 /// </summary>
 /// <param name="reader">The reader.</param>
 public RecordCreator(CsvReader reader)
 {
     Reader            = reader;
     ExpressionManager = new ExpressionManager(reader);
 }
Exemple #9
0
 /// <summary>
 /// Creates a new instance using the given reader.
 /// </summary>
 /// <param name="reader">The reader.</param>
 public RecordHydrator(CsvReader reader)
 {
     this.reader       = reader;
     expressionManager = ObjectResolver.Current.Resolve <ExpressionManager>(reader);
 }