Tuesday, October 3, 2017

a reflection-based solution for drinking up records with LinqToExcel when there are not explicit column names

I'm going to have a "NoteAttribute" attribute as described here only AttributeTargets.Method will be replaced with AttributeTargets.Property as we will be dealing with the pseudogetsetters that are auto-properties in lieu of methods. I'm basically tackling this problem and keeping the logs variable as descibed only it will be a List<RowNoHeader> instead of an IQueryable<RowNoHeader> but this change like the other change is really a pretty small thing. The important thing to know is that the records we drink off of a LinqToExcel scrapping end up in the variable called logs. We use it like so:

int pseudoHeaderPosition = 8;
List<WeldLog> weldLogs = new List<WeldLog>() {};
int outerCounter = 0;
Dictionary<int, int> dictionary = new Dictionary<int, int>();
Type type = typeof(WeldLog);
PropertyInfo[] propertyInfos = type.GetProperties();
while (outerCounter < propertyInfos.Length)
{
   var metadata = propertyInfos[outerCounter].CustomAttributes.ElementAt(0)
         .ConstructorArguments[0].Value.ToString().Trim();
   int innerCounter = 0;
   while (innerCounter < logs[pseudoHeaderPosition].Count)
   {
      var pseudoHeader =
            logs[pseudoHeaderPosition][innerCounter].Value.ToString().Trim();
      if (metadata == pseudoHeader)
      {
         dictionary.Add(innerCounter,outerCounter);
      }
      innerCounter++;
   }
   outerCounter++;
}
outerCounter = pseudoHeaderPosition + 1;
while (outerCounter < logs.Count)
{
   WeldLog weldLog = new WeldLog();
   foreach (KeyValuePair<int, int> keyValuePair in dictionary)
   {
      var setting = logs[outerCounter][keyValuePair.Key].Value;
      SetIt(weldLog, propertyInfos[keyValuePair.Value], (dynamic)setting);
   }
   weldLogs.Add(weldLog);
   outerCounter++;
}

 
 

Alright, clearly (well, maybe it's not so clear) we will end up with the weldLogs variable hydrated with WeldLog records on the other side of this procedural blob and clearly WeldLog has a bunch of auto-properties on it and those auto-properties have at least one attribute each that is getting found as the first attribute for every auto-property. As you might surmise, the attribute is the NoteAttribute. The code above assumes that the 9th row of the Excel sheet contains pseudoheaders for columns (while the first 8 rows contain a fat header with various notes) and the rows after have the actual data. The WeldLog POCO looks like so:

namespace WelderConsoleApp.Logic
{
   public class WeldLog
   {
      [Note("Area")]
      public string Area { get; set; }
      
      [Note("Drawing #")]
      public string DrawingNumber { get; set; }
      
      [Note("Item #")]
      public string ItemNumber { get; set; }
      
      [Note("Weld #")]
      public string WeldNumber { get; set; }
      
      [Note("Unit")]
      public string Unit { get; set; }
   }
}

 
 

What about the SetIt method which clearly uses some dynamic magic? It looks like so:

private void SetIt(WeldLog weldLog, PropertyInfo propertyInfo, object setting)
{
   
//do nothing
}
 
private void SetIt(WeldLog weldLog, PropertyInfo propertyInfo, string setting)
{
   propertyInfo.SetValue(weldLog, setting);
}
 
private void SetIt(WeldLog weldLog, PropertyInfo propertyInfo, System.DBNull setting)
{
   
//do nothing
}

No comments:

Post a Comment