Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the ability to have custom logic to read field values #428

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions FileHelpers.Tests/Tests/Common/RecordOptionsTests.cs
Original file line number Diff line number Diff line change
@@ -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<SampleTypeCustomAttribute>();

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<ICustomAttribute>();

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;
}
}
}
14 changes: 14 additions & 0 deletions FileHelpers.Tests/Types/SampleTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 { }
}
4 changes: 2 additions & 2 deletions FileHelpers/Core/RecordOperations.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,11 +166,11 @@ private bool MustIgnoreLine(string line)
/// </summary>
/// <param name="record">Object to convert</param>
/// <returns>String representing the object</returns>
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]);
Expand Down
2 changes: 1 addition & 1 deletion FileHelpers/Core/ReflectionHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace FileHelpers
/// </summary>
/// <param name="record">instance to extract from</param>
/// <returns>Values from the instance</returns>
internal delegate object[] ObjectToValuesDelegate(object record);
public delegate object[] ObjectToValuesDelegate(object record);

/// <summary>
/// Create an object (function created based upon a type)
Expand Down
2 changes: 1 addition & 1 deletion FileHelpers/Engines/EventEngineBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
13 changes: 12 additions & 1 deletion FileHelpers/Engines/RecordOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,17 @@ public RecordConditionInfo RecordCondition
get { return mRecordConditionInfo; }
}

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private ObjectToValuesDelegate mObjectToValuesHandler;

/// <summary>
/// Used to provide custom logic for getting the values of fields.
/// marker.
/// </summary>
public ObjectToValuesDelegate ObjectToValuesHandler {
get { return mObjectToValuesHandler; }
set { mObjectToValuesHandler = value; }
}

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly IgnoreCommentInfo mIgnoreCommentInfo;
Expand Down Expand Up @@ -270,7 +281,7 @@ public bool InAnyPlace
/// <returns>The string representation of the current record</returns>
public string RecordToString(object record)
{
return mRecordInfo.Operations.RecordToString(record);
return mRecordInfo.Operations.RecordToString(record, ObjectToValuesHandler);
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion FileHelpers/Fields/FieldBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public abstract class FieldBase
/// <summary>
/// Details about the extraction criteria
/// </summary>
internal FieldInfo FieldInfo { get; private set; }
public FieldInfo FieldInfo { get; private set; }

/// <summary>
/// indicates whether we trim leading and/or trailing whitespace
Expand Down
4 changes: 2 additions & 2 deletions FileHelpers/MasterDetail/MasterDetailEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -453,14 +453,14 @@ public void WriteStream(TextWriter writer, IEnumerable<MasterDetails<TMaster, TD
if (MustNotifyProgress) // Avoid object creation
OnProgress(new ProgressEventArgs(recIndex + 1, max));

currentLine = mMasterInfo.Operations.RecordToString(rec.Master);
currentLine = mMasterInfo.Operations.RecordToString(rec.Master, Options.ObjectToValuesHandler);
writer.WriteLine(currentLine);

if (rec.Details != null)
{
for (int d = 0; d < rec.Details.Length; d++)
{
currentLine = RecordInfo.Operations.RecordToString(rec.Details[d]);
currentLine = RecordInfo.Operations.RecordToString(rec.Details[d], Options.ObjectToValuesHandler);
writer.WriteLine(currentLine);
}
}
Expand Down