public static Func <object[], T> CreateMapper <T>(this Dbf dbf) where T : class, new() { var fields = dbf.GetHeader().Fields; var type = typeof(T); var props = type.GetProperties(); var methodBody = new List <Expression>(); var rowParam = Expression.Parameter(typeof(object[]), "row"); var hoistedLocalVariable = Expression.Property(Expression.Constant(new ValueBag <T>()), "Value"); methodBody.Add(Expression.Assign(hoistedLocalVariable, Expression.New(type))); for (int i = 0; i < fields.Count; i++) { var field = fields[i]; var prop = props.FirstOrDefault(x => x.Name.Equals(field.Name, StringComparison.OrdinalIgnoreCase)); if (prop is null) { continue; } var value = Expression.ArrayIndex(rowParam, Expression.Constant(field.Index)); var access = Expression.MakeMemberAccess(hoistedLocalVariable, prop); var setter = Expression.Assign(access, Expression.Convert(value, prop.PropertyType)); methodBody.Add(setter); } var returnTarget = Expression.Label(type); methodBody.Add(Expression.Return(returnTarget, hoistedLocalVariable, type)); methodBody.Add(Expression.Label(returnTarget, hoistedLocalVariable)); var lambda = Expression.Lambda <Func <object[], T> >(Expression.Block(methodBody), rowParam); return(lambda.Compile()); }
public DbfReader(Dbf dbf, Encoding textEncoding) { DbfTypeMap.Add('C', (i, b, f, e) => { if (f.Length == 1) { return(e.GetString(b)[0]); } return(e.GetString(b).TrimEnd('\0')); }); DbfTypeMap.Add('M', (i, b, f, e) => BitConverter.ToInt32(b)); DbfTypeMap.Add('W', (i, b, f, e) => BitConverter.ToInt32(b)); DbfTypeMap.Add('G', (i, b, f, e) => BitConverter.ToInt32(b)); DbfTypeMap.Add('Y', (i, b, f, e) => BitConverter.ToInt64(b) / 10000m); // Stored as int64 with 4 implicit decimal places DbfTypeMap.Add('D', (i, b, f, e) => { var dateStr = e.GetString(b).Trim(); return(dateStr == "" ? DateTime.MinValue : DateTime.ParseExact(dateStr, "yyyyMMdd", null)); }); DbfTypeMap.Add('T', (i, b, f, e) => JulianDateHelper.FromULongBuffer(b)); DbfTypeMap.Add('N', (i, b, f, e) => { var numStr = e.GetString(b).Trim(); if (f.DecimalCount == 0) { if (f.Length < 3) { if (numStr == "") { return((byte)0); } return(byte.Parse(numStr)); } else if (f.Length < 5) { if (numStr == "") { return((short)0); } return(short.Parse(numStr)); } else if (f.Length < 10) { if (numStr == "") { return((int)0); } return(int.Parse(numStr)); } else if (f.Length < 19) { if (numStr == "") { return((long)0); } return(long.Parse(numStr)); } } return(numStr == "" ? 0m : decimal.Parse(numStr)); }); DbfTypeMap.Add('B', (i, b, f, e) => BitConverter.ToInt32(b)); DbfTypeMap.Add('O', (i, b, f, e) => BitConverter.ToDouble(b)); DbfTypeMap.Add('F', (i, b, f, e) => { var numStr = e.GetString(b).Trim(); return(numStr == "" ? 0f : float.Parse(numStr)); }); DbfTypeMap.Add('I', (i, b, f, e) => BitConverter.ToInt32(b)); DbfTypeMap.Add('L', (i, b, f, e) => BitConverter.ToBoolean(b)); DbfTypeMap.Add('Q', CopyFieldBuffer); DbfTypeMap.Add('P', CopyFieldBuffer); this.dbf = dbf; TextEncoding = textEncoding; dbfHeader = dbf.GetHeader(); if (IsVisualFoxPro(dbfHeader)) { // Special handling for VFP DbfTypeMap['B'] = (i, b, f, e) => BitConverter.ToDouble(b); // VarChar/VarBinary // SPECIAL CASE for VARCHAR/BINARY DbfTypeMap['V'] = (i, b, f, e) => f.Flags.HasFlag(DbfFieldFlags.Binary) ? CopyFieldBuffer(i, b, f, e) : e.GetString(b); // _NullFlags nullField = dbfHeader.Fields.FirstOrDefault(x => x.Type == '0'); nullFieldDataHandler = DbfTypeMap['0'] = CopyFieldBuffer; if (nullField != null) { if (nullField.Length == 1) { nullFieldHandlerFactory = (i, b, f, e) => new UIntNullFieldHandler(b[0]); } else { nullFieldHandlerFactory = (i, b, f, e) => new BitArrayNullFieldHandler(b.ToArray()); } } } }