using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Runtime.CompilerServices;
using ImpromptuInterface;
using Dynamitey;
namespace DotNetDBF.Enumerable
{
///
/// Interface to get the contents of the DBF Wrapper
///
public interface IDBFInterceptor
{
///
/// Does field exist in row
///
///
bool Exists(string fieldName);
///
/// Gets the data row.
///
///
object[] GetDataRow();
}
#pragma warning disable 618
public class DBFInterceptor : DBFIntercepter
#pragma warning restore 618
{
public DBFInterceptor(object[] wrappedObj, string[] fieldNames) : base(wrappedObj, fieldNames)
{
}
}
///
/// DBF Dynamic Wrapper
///
public abstract class BaseDBFInterceptor : Dynamitey.DynamicObjects.BaseObject, IDBFInterceptor
{
private readonly string[] _fieldNames;
private readonly object[] _wrappedArray;
protected BaseDBFInterceptor(object[] wrappedObj, string[] fieldNames)
{
_wrappedArray = wrappedObj;
_fieldNames = fieldNames;
}
public override IEnumerable GetDynamicMemberNames()
{
return _fieldNames;
}
public bool Exists(string fieldName)
{
return _fieldNames.Contains(fieldName);
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
var tLookup = binder.Name;
var tIndex = Array.FindIndex(_fieldNames,
it => it.Equals(tLookup, StringComparison.InvariantCultureIgnoreCase));
if (tIndex < 0)
return false;
result = _wrappedArray[tIndex];
if (TryTypeForName(tLookup, out var outType))
{
result = Dynamic.CoerceConvert(result, outType);
}
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
var tLookup = binder.Name;
var tIndex = Array.FindIndex(_fieldNames,
it => it.Equals(tLookup, StringComparison.InvariantCultureIgnoreCase));
if (tIndex < 0)
return false;
if (TryTypeForName(tLookup, out var outType))
{
value = Dynamic.CoerceConvert(value, outType);
}
_wrappedArray[tIndex] = value;
return true;
}
public object[] GetDataRow()
{
return _wrappedArray;
}
}
///
/// Enumerable API
///
public static partial class DBFEnumerable
{
///
/// New Blank Row Dynamic object that matches writer;
///
/// The writer.
///
public static dynamic NewBlankRow(this DBFWriter writer)
{
var fields = writer.Fields.Select(it => it.Name).ToArray();
var obj = new object[fields.Length];
return new Enumerable.DBFInterceptor(obj, fields);
}
public static void CopyRecordTo(this IDBFInterceptor original, IDBFInterceptor dest)
{
foreach (var fieldName in Dynamitey.Dynamic.GetMemberNames(dest, true))
{
try
{
var val = Dynamic.InvokeGet(original, fieldName);
Dynamic.InvokeSet(dest, fieldName, val);
}
catch
{
// ignored
}
}
}
///
/// Writes the record.
///
/// The writer.
/// The value.
public static void WriteRecord(this DBFWriter writer, Enumerable.IDBFInterceptor value)
{
writer.WriteRecord(value.GetDataRow());
}
///
/// Adds the record.
///
/// The writer.
/// The value.
public static void AddRecord(this DBFWriter writer, Enumerable.IDBFInterceptor value)
{
writer.AddRecord(value.GetDataRow());
}
///
/// Return all the records. T should be interface with getter properties that match types and names of the database.
/// Optionally instead of T being and interface you can pass in an anonymous object with properties that match that
/// database and then you'll get an IEnumerable of that anonymous type with the data filled in.
///
///
/// The reader.
/// The prototype. Anonymous class instance
/// Indicates if parsing error throws an exception. Default: true
///
public static IEnumerable AllRecords(this DBFReader reader, T prototype = null, bool throwOnParsingError = true) where T : class
{
var tType = typeof(T);
var tProperties = tType.GetProperties()
.Where(
it =>
Array.FindIndex(reader.Fields,
f => f.Name.Equals(it.Name, StringComparison.InvariantCultureIgnoreCase)) >= 0)
.ToList();
var tProps = tProperties
.Select(
it =>
Array.FindIndex(reader.Fields,
jt => jt.Name.Equals(it.Name, StringComparison.InvariantCultureIgnoreCase)))
.Where(it => it >= 0)
.ToArray();
var tOrderedProps = tProps.OrderBy(it => it).ToArray();
var tReturn = new List();
if (tType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any())
{
var tAnon = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
while (tAnon != null)
{
tReturn.Add((T) Activator.CreateInstance(tType, tAnon));
tAnon = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
}
return tReturn;
}
var t = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
while (t != null)
{
var interceptor = new Enumerable.DBFInterceptor(t, tProperties.Select(it => it.Name).ToArray());
tReturn.Add(interceptor.ActLike(typeof(Enumerable.IDBFInterceptor)));
t = reader.NextRecord(tProps, tOrderedProps, throwOnParsingError);
}
return tReturn;
}
///
/// Returns a list of dynamic objects whose properties and types match up with that database name.
///
/// The reader.
/// The where column name.
/// What the were column should equal.
/// Indicates if parsing error throws an exception. Default: true
///
public static IEnumerable DynamicAllRecords(this DBFReader reader, string whereColumn = null,
dynamic whereColumnEquals = null, bool throwOnParsingError = true)
{
var props = reader.GetSelectFields().Select(it => it.Name).ToArray();
int? whereColumnIndex = null;
if (!String.IsNullOrEmpty(whereColumn))
{
whereColumnIndex = Array.FindIndex(props,
it => it.Equals(whereColumn, StringComparison.InvariantCultureIgnoreCase));
}
var tReturn = new List