NetSuite自定义记录搜索将结果转换为.NET对象列表

时间:2015-12-15 21:09:31

标签: c# web-services soap netsuite

我能够做到的唯一方法是通过下面的基于反射的代码。我不敢相信没有“更简单的NetSuite方式”来做到这一点?我错过了一些基本的东西吗?

在我对自定义对象执行搜索后,我返回了一个Record[]数组,然后可以将其循环并将每个项目转换为CustomObject

自定义对象的属性存储在CustomRecord的{​​{1}}中,但是无法立即访问这些值,您必须将那些强制转换为真正的NetSuite类型(例如customFieldListLongCustomFieldRefDoubleCustomFieldRefBooleanCustomFieldRef等。

为了不必为了得到漂亮干净的物品而烦恼,我决定采用下面的方法:

创建具有匹配(包括大小写)NetSuite名称的属性名称的类,并继承自NetSuiteBase(在下面定义)

StringCustomFieldRef

创建一个基类,它将检查CustomRecords并将属性值应用于.NET类

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;
    }
}

在自定义对象上执行NetSuite搜索后,循环搜索结果并使用上述类将NetSuite结果转换为.NET类

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;
            }
        }

    }
}

还有其他“NetSuite方法”来完成我上面的工作吗?

1 个答案:

答案 0 :(得分:0)

否,没有“ NetSuite”方式。如果您问我,您所做的工作远远超出了职责范围,这太了不起了。 NetSuite / SuiteTalk WSDL太糟糕了,在设计过程中做出了很多错误的选择,令我震惊的是,它原封不动地发布给了开发人员,没有提出任何问题。下面是另一个示例。

Bad API construction

这来自于SuiteTalk课程的文档,该文档揭示了在解析“高级”搜索的结果时,它们包含在其中的SearchRowBasic对象。每个SearchRowBasic对象中都有多个字段。要访问这些字段的值,您必须使用SearchColumnField数组的第一个元素。你为什么要这样做?如果只有一个值(并且他们在文档中指出确实是只有一个值),那么为什么要将返回对象作为数组而不是仅仅将返回值传递给开发人员呢?基本类型本身直接???那只是很糟糕的API构造,迫使开发人员每次都使用SearchColumnField [0] .searchValue而不是SearchColumnField.searchValue!