title: NetSuite Custom Record Search Convert Results into List of .NET Objects
body: <p>The only way I've been able to do it is through the reflection-based code below.  I can't believe there's not an "easier NetSuite way" to do this though?  Am I missing something basic?</p>
  
  <p>After I perform a search on custom objects I get back an array of <code>Record[]</code>, this can then be looped through and each item casted to a <code>CustomObject</code>.</p>
  
  <p>The properties of the custom object are stored in the <code>CustomRecord</code>'s <code>customFieldList</code> but the values are not immediately accessible you have to cast <em>those</em> the their real NetSuite type (like <code>LongCustomFieldRef</code>, <code>DoubleCustomFieldRef</code>, <code>BooleanCustomFieldRef</code>, <code>StringCustomFieldRef</code>, etc).</p>
  
  <p>In order to not have to bother with this mess to get nice clean objects on my side I decided on the approach below:</p>
  
  <p><strong>Create classes with property names that match (including case) the NetSuite names and inherits from NetSuiteBase (defined below)</strong></p>
  
  <pre><code>public class MyNetSuiteObject : NetSuiteBase //&lt;-- Note base class
  {
      public string myProperty1 { get; set; }
      public bool myProperty2 { get; set; }
      public int myProperty3 { get; set; }
  
      public static MyNetSuiteObject FromCustomSearchRecord(CustomRecord customRecord)
      {
          var ret = new MyNetSuiteObject();
          ret.AssignProperties(customRecord);
          return ret;
      }
  }
  </code></pre>
  
  <p><strong>Create a base class which will inspect CustomRecords and apply property values to the .NET classes</strong></p>
  
  <pre><code>public class NetSuiteBase
  {
  
      public void AssignProperties(CustomRecord customRecord)
      {
          var classProps = this.GetType().GetProperties();
          foreach (var prop in classProps)
          {
              var propName = prop.Name;
              var propValue = prop.GetValue(this, null);
  
              //get the matching CustomFieldRef out of the customFieldList for the CustomRecord which matches our current property name
              var myCustomFieldRef = customRecord.customFieldList.Where(c =&gt; c.scriptId == propName).FirstOrDefault();
  
              if (myCustomFieldRef == null) continue;
  
              //we can't get the value out until we cast the CustomFieldRef to its "actual" type.
              var custType = myCustomFieldRef.GetType().Name;
              switch (custType)
              {
                  case "LongCustomFieldRef":
                      TrySetProperty(prop, ((LongCustomFieldRef)myCustomFieldRef).value.ToString());
                      break;
  
                  case "DoubleCustomFieldRef":
                      TrySetProperty(prop, ((DoubleCustomFieldRef)myCustomFieldRef).value.ToString());
                      break;
  
                  case "BooleanCustomFieldRef":
                      TrySetProperty(prop, ((BooleanCustomFieldRef)myCustomFieldRef).value.ToString());
                      break;
  
                  case "StringCustomFieldRef":
                      TrySetProperty(prop, ((StringCustomFieldRef)myCustomFieldRef).value.ToString());
                      break;
  
                  case "DateCustomFieldRef":
                      TrySetProperty(prop, ((DateCustomFieldRef)myCustomFieldRef).value.ToString());
                      break;
  
                  case "SelectCustomFieldRef":
                      TrySetProperty(prop, ((SelectCustomFieldRef)myCustomFieldRef).value.name.ToString());
                      break;
  
                  case "MultiSelectCustomFieldRef":
                      TrySetProperty(prop, ((MultiSelectCustomFieldRef)myCustomFieldRef).value.ToString());
                      break;
                  default:
                      Console.WriteLine("Unknown type: " + myCustomFieldRef.internalId);
                      break;
              }
          }
      }
  
  
      //Some of the NetSuite properties are represented as strings (I'm looking at you BOOLs), so we pass all the values from above
      //as strings and them process/attempt casts
      private void TrySetProperty(PropertyInfo prop, string value)
      {
          value = value.ToLower().Trim();
  
          if (prop.PropertyType == typeof(string))
          {
              prop.SetValue(this, value);
              return;
          }
  
  
          if (prop.PropertyType == typeof(bool))
          {
              if (value == "yes") value = "true";
              if (value == "no") value = "false";
              if (value == "1") value = "true";
              if (value == "0") value = "false";
  
              bool test;
              if (bool.TryParse(value, out test))
              {
                  prop.SetValue(this, test);
                  return;
              }
          }
  
          if (prop.PropertyType == typeof(int))
          {
              int test;
              if (int.TryParse(value, out test))
              {
                  prop.SetValue(this, test);
                  return;
              }
          }
  
          if (prop.PropertyType == typeof(double))
          {
              double test;
              if (double.TryParse(value, out test))
              {
                  prop.SetValue(this, test);
                  return;
              }
          }
  
          if (prop.PropertyType == typeof(decimal))
          {
              decimal test;
              if (decimal.TryParse(value, out test))
              {
                  prop.SetValue(this, test);
                  return;
              }
          }
  
      }
  }
  </code></pre>
  
  <p><strong>After performing a NetSuite search on custom objects, loop through the results and use the above classes to convert NetSuite result to a .NET class</strong></p>
  
  <pre><code>for (int i = 0, j = 0; i &lt; records.Length; i++, j++)
  {
      customRecord = (CustomRecord)records[i];
  
      var myNetSuiteObject = MyNetSuiteObject.FromCustomSearchRecord(customRecord);
  }
  </code></pre>
  
  <p>Is there some other "NetSuite way" to accomplish what I have above?</p>