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?
After I perform a search on custom objects I get back an array of Record[]
, this can then be looped through and each item casted to a CustomObject
.
The properties of the custom object are stored in the CustomRecord
's customFieldList
but the values are not immediately accessible you have to cast those the their real NetSuite type (like LongCustomFieldRef
, DoubleCustomFieldRef
, BooleanCustomFieldRef
, StringCustomFieldRef
, etc).
In order to not have to bother with this mess to get nice clean objects on my side I decided on the approach below:
Create classes with property names that match (including case) the NetSuite names and inherits from NetSuiteBase (defined below)
public class MyNetSuiteObject : NetSuiteBase //<-- 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;
}
}
Create a base class which will inspect CustomRecords and apply property values to the .NET classes
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 => 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;
}
}
}
}
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
for (int i = 0, j = 0; i < records.Length; i++, j++)
{
customRecord = (CustomRecord)records[i];
var myNetSuiteObject = MyNetSuiteObject.FromCustomSearchRecord(customRecord);
}
Is there some other "NetSuite way" to accomplish what I have above?