2

Im new to C# so i may be way off with what i think is the issue but... Im using a 3rd party SDK to manage loan data. i have a method "GetPayload()" which opens a loan and gets the most recent field change info into "datalist".

public object GetPayload()
    {
        // create list to hold field change data
        List<Ignite.Auditing.DataTypes.Request.Field> DataList = new List<Ignite.Auditing.DataTypes.Request.Field>();

        //create and open new session and loan based on user entered GUID            
        Session ses = OpenSession();
        Loan loan = ses.Loans.Open(loanGuidTextBox.Text);

        //call method to get the field change data for this loan
        AuditTrailEntryList dataList = loan.AuditTrail.GetMostRecentEntries();

        Type myTypeB = typeof(AuditTrailEntry);
        FieldInfo myFieldInfo1 = myTypeB.GetField("auditRecord", BindingFlags.NonPublic | BindingFlags.Instance);


        foreach (AuditTrailEntry entry in dataList)
        {

            FieldInfo[] fields = entry.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance);
          //  FieldInfo value = (FieldInfo)myFieldInfo1.GetValue(entry.auditRecord.PreviousValue);

            FieldData fd = new FieldData
            {
                FieldDated = entry.Timestamp.ToUniversalTime(),
                FieldDescription = entry.Field.Descriptor.ToString(),
                FieldFormat = entry.Field.Format.ToString(),
                FieldId = entry.Field.ID.ToString(),
                NewValue = entry.Field.Value.ToString(),
                // OldValue = e.PriorValue,
                //OldValue = fce.PriorValue,

                OldValue = myFieldInfo1.GetValue(entry).ToString(),

            };                
            DataList.Add(fd);
        }           


        return _serviceInfo.RequestData;
    }

From there, i do a foreach on each entry in the datalist which has the info i need. i then populate a "FieldData" object (fd) with the needed data. the problem is that one of the fields i need seems to be in what i think is a private field based on what i saw in the debugger (the lock icon next to "auditRecord"). debugger screen shot how do i access "entry.auditRecord.PreviousValue"? ive used Type.GetField (documentation) to get the private member, which kinda works in that it gets "auditRecord", but how do i drill down to the next member i.e auditRecord.PreviousValue? i just want to get the OldValue, which i thought should be entry.auditRecord.PreviousValue but it seems to be inaccessible. No error msg just the wrong values. can someone help?

Duan Walker
  • 305
  • 1
  • 11
  • `typeof(AuditTrailEntry).GetProperty("auditRecord")` should return the specified object for the audit record. Then from there, you should be able `GetProperties` or `GetProperty("PreviousValue")` to get the value or set the value. – Greg Nov 01 '18 at 20:08
  • 1
    Is working with the provider of this class to gain access to your needed information an option? In other words, can someone make the field public or provide an accessor method. If it's indeed needed by 3rd party users, then there's a problem with the design of the class. – sean Nov 01 '18 at 21:12
  • @sean i dont disagree that this is a poor design. but no, i cant make the field public. thanks – Duan Walker Nov 02 '18 at 13:16
  • can anyone confirm that the lock icon in the debugger means that the field is private or does it mean something else? – Duan Walker Nov 02 '18 at 13:19
  • 1
    @DuanWalker The lock indicates the access is `private`. Here is a legend for the icons: https://learn.microsoft.com/en-us/visualstudio/ide/class-view-and-object-browser-icons?view=vs-2015 – Xiaoy312 Nov 03 '18 at 09:20
  • @Xiaoy312 man thanks a mil! – Duan Walker Nov 05 '18 at 14:29

2 Answers2

3

Guessing by the naming convention, auditRecord is a field and PreviousValue is a property.

To extract value by reflection, you need to navigate layer by layer:

var auditRecordField = typeof(AuditTrailEntry).GetField("auditRecord", BindingFlags.NonPublic | BindingFlags.Instance);
var previousValueProperty = auditRecordField.FieldType.GetProperty("PreviousValue", BindingFlags.NonPublic | BindingFlags.Instance);

// ...

foreach (AuditTrailEntry entry in dataList)
{
    // ...

    var record = auditRecordField.GetValue(entry);
    var value = previousValueProperty.GetValue(record);
}
Xiaoy312
  • 14,292
  • 1
  • 32
  • 44
  • thanks for the assist. i think this works, however sometimes the PreviousValue is null and not sure how to handle those instances. visual studio is yelling at me now about a null ref exception at the line "previousValueProperty.GetValue(record)". any ideas on how to fix this? – Duan Walker Nov 02 '18 at 20:28
  • 1
    In that case, `auditRecord` might be null for some entries. Just replace the last line by: `var value = record != null ? previousValueProperty.GetValue(record) : default;` – Xiaoy312 Nov 03 '18 at 09:16
0

@xiaoy312 i finally got it! the way i got it to work was to include another dll "EllieMae.EMLite.ClientServer". i was told by my non programmer manager that all the info i needed was in the dlls he provided but he was wrong. for anyone experiencing this issue in the future i had to use

            //get the type info for the audit trail entry
            FieldInfo myFieldInfo1 = typeof(AuditTrailEntry).GetField("auditRecord", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.GetField);

            //get the value for auditRecord field
            var value = myFieldInfo1.GetValue(entry);

            //get old value field
            var oldValue = ((EllieMae.EMLite.ClientServer.AuditRecord)value).PreviousValue;

to get the old value from the AuditTrailEntry object. thanks for your help!

Duan Walker
  • 305
  • 1
  • 11