diff --git a/FileHelpers.Tests/Tests/Common/RecordOptionsTests.cs b/FileHelpers.Tests/Tests/Common/RecordOptionsTests.cs new file mode 100644 index 00000000..c8dc4b0f --- /dev/null +++ b/FileHelpers.Tests/Tests/Common/RecordOptionsTests.cs @@ -0,0 +1,61 @@ +using System; +using System.IO; +using System.Linq; +using FileHelpers.Options; +using NUnit.Framework; + +namespace FileHelpers.Tests.CommonTests +{ + [TestFixture] + public class RecordOptionsTests + { + [Test] + public void ReadFileNotifyRecord() + { + var engine = new DelimitedFileEngine(); + + engine.Options.ObjectToValuesHandler = x => Process(x, engine.Options); + + var res = engine.WriteString(new SampleTypeCustomAttribute[] { + new SampleTypeCustomAttribute() { One = 100, Two = 200 }, + new SampleTypeCustomAttribute() { One = 300, Two = 400 }, + }); + + var expected = "101,-201\r\n301,-401\r\n"; + Assert.AreEqual(expected, res); + } + + private object[] Process(object obj, RecordOptions options) { + var result = new object[options.FieldCount]; + + for (var i = 0; i < options.FieldCount; i++) { + result[i] = GetValueByAttributes(obj, options.Fields[i]); + } + + return result; + } + + private object GetValueByAttributes(object obj, FieldBase fieldBase) { + var value = (int)fieldBase.FieldInfo.GetValue(obj); + + if (fieldBase.FieldType == typeof(int)) { + var attribs = fieldBase.FieldInfo + .GetCustomAttributes(false) + .OfType(); + + var number = (int)value; + foreach (var attrib in attribs) { + if (attrib is AddOneAttribute) { + number++; + } + else if (attrib is NegativeAttribute) { + number = -number; + } + } + value = number; + } + + return value; + } + } +} \ No newline at end of file diff --git a/FileHelpers.Tests/Types/SampleTypes.cs b/FileHelpers.Tests/Types/SampleTypes.cs index 5c096cf4..197f5ba1 100644 --- a/FileHelpers.Tests/Types/SampleTypes.cs +++ b/FileHelpers.Tests/Types/SampleTypes.cs @@ -79,4 +79,18 @@ public class SampleTypeNullableGuid { public Guid? Field1; } + + [DelimitedRecord(",")] + public class SampleTypeCustomAttribute + { + [AddOne] + public int One; + [AddOne] + [Negative] + public int Two; + } + + public class AddOneAttribute : Attribute, ICustomAttribute { } + public class NegativeAttribute : Attribute, ICustomAttribute { } + public interface ICustomAttribute { } } \ No newline at end of file diff --git a/FileHelpers/Core/RecordOperations.cs b/FileHelpers/Core/RecordOperations.cs index 18ec0bdf..90ce55fe 100644 --- a/FileHelpers/Core/RecordOperations.cs +++ b/FileHelpers/Core/RecordOperations.cs @@ -166,11 +166,11 @@ private bool MustIgnoreLine(string line) /// /// Object to convert /// String representing the object - public string RecordToString(object record) + public string RecordToString(object record, ObjectToValuesDelegate objectToValuesHandler) { var sb = new StringBuilder(mRecordInfo.SizeHint); - var values = ObjectToValuesHandler(record); + var values = objectToValuesHandler?.Invoke(record) ?? ObjectToValuesHandler(record); for (int f = 0; f < mRecordInfo.FieldCount; f++) mRecordInfo.Fields[f].AssignToString(sb, values[f]); diff --git a/FileHelpers/Core/ReflectionHelper.cs b/FileHelpers/Core/ReflectionHelper.cs index 57dfbf1e..d7c0ac35 100644 --- a/FileHelpers/Core/ReflectionHelper.cs +++ b/FileHelpers/Core/ReflectionHelper.cs @@ -25,7 +25,7 @@ namespace FileHelpers /// /// instance to extract from /// Values from the instance - internal delegate object[] ObjectToValuesDelegate(object record); + public delegate object[] ObjectToValuesDelegate(object record); /// /// Create an object (function created based upon a type) diff --git a/FileHelpers/Engines/EventEngineBase.cs b/FileHelpers/Engines/EventEngineBase.cs index 6279b3b8..0a2c8e40 100644 --- a/FileHelpers/Engines/EventEngineBase.cs +++ b/FileHelpers/Engines/EventEngineBase.cs @@ -208,7 +208,7 @@ internal void WriteRecord(T record, int recordIndex, int totalRecord, TextWriter if (skip == false) { - currentLine = info.Operations.RecordToString(record); + currentLine = info.Operations.RecordToString(record, Options.ObjectToValuesHandler); if (mustNotifyWriteForRecord) { diff --git a/FileHelpers/Engines/RecordOptions.cs b/FileHelpers/Engines/RecordOptions.cs index 0682e886..c8ce9a8b 100644 --- a/FileHelpers/Engines/RecordOptions.cs +++ b/FileHelpers/Engines/RecordOptions.cs @@ -159,6 +159,17 @@ public RecordConditionInfo RecordCondition get { return mRecordConditionInfo; } } + [DebuggerBrowsable(DebuggerBrowsableState.Never)] + private ObjectToValuesDelegate mObjectToValuesHandler; + + /// + /// Used to provide custom logic for getting the values of fields. + /// marker. + /// + public ObjectToValuesDelegate ObjectToValuesHandler { + get { return mObjectToValuesHandler; } + set { mObjectToValuesHandler = value; } + } [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly IgnoreCommentInfo mIgnoreCommentInfo; @@ -270,7 +281,7 @@ public bool InAnyPlace /// The string representation of the current record public string RecordToString(object record) { - return mRecordInfo.Operations.RecordToString(record); + return mRecordInfo.Operations.RecordToString(record, ObjectToValuesHandler); } /// diff --git a/FileHelpers/Fields/FieldBase.cs b/FileHelpers/Fields/FieldBase.cs index 37d7b40d..d9c85466 100644 --- a/FileHelpers/Fields/FieldBase.cs +++ b/FileHelpers/Fields/FieldBase.cs @@ -84,7 +84,7 @@ public abstract class FieldBase /// /// Details about the extraction criteria /// - internal FieldInfo FieldInfo { get; private set; } + public FieldInfo FieldInfo { get; private set; } /// /// indicates whether we trim leading and/or trailing whitespace diff --git a/FileHelpers/MasterDetail/MasterDetailEngine.cs b/FileHelpers/MasterDetail/MasterDetailEngine.cs index c6f6a0fb..81b12536 100644 --- a/FileHelpers/MasterDetail/MasterDetailEngine.cs +++ b/FileHelpers/MasterDetail/MasterDetailEngine.cs @@ -453,14 +453,14 @@ public void WriteStream(TextWriter writer, IEnumerable