0

我正在尝试将Highrise Apiscottschluer 的 .NET 4.5 包装器一起使用,以便将新人员连同他们输入的任何自定义数据一起发布到我们的 Highrise 帐户。

我遇到的问题是自定义数据。人对象发布得很好,但主题数据字段不包含在帖子中。

我确实遇到过这篇文章:Highrise Custom Fields。看起来缺少的东西是type="array"该字段的属性subject_datas。我通过使用我试图发布的对象的序列化值手动创建请求来测试这个假设。此测试的结果是成功发布到服务器,并填充了所有自定义数据字段。

我尝试从包装程序集中扩展类以将缺少的属性添加到列表中,但这似乎仍然不起作用。Person 对象具有 SubjectData 对象列表的属性,我在子类中覆盖了该属性以改用自定义类。这样我可以添加一个属性作为属性。这个自定义类似乎仍然不起作用。

查看RestSharp 的 XmlSerializer的代码后,它似乎只会在该对象实现 IList 时添加项目列表。这不是问题,我能够让它工作,但代码似乎不允许向列表元素添加属性。它只查看列表类的子类并忽略对象上的任何其他属性。

所以我的问题是:

是否可以将属性应用于 RestSharp 中的列表属性,或者是否有另一种方法可以在发送请求之前将type="array"属性添加到data_subjectsxml 节点?

4

1 回答 1

1

我最终通过创建一个新的请求类自己解决了这个问题,该类将使用自定义 XmlSerializer 创建一个 RestRequest。

然后我扩展了 Person 类并将属性隐藏在自定义列表对象属性后面

前:

[SerializeAs(Name = "subject_datas")]
public List<SubjectData> SubjectDatas { get; set; }

后:

[SerializeAs(Name = "subject_datas")]
public new SubjectDataList SubjectDatas { get; set; }

该类SubjectDataList只是List<SubjectData>.

SubjectDataList实现一个名为的接口ISerializeList<SubjectData> ,其定义为:

interface ISerializeList : IEnumerable {}
interface ISerializeList<T> :IEnumerable<T>, ISerializeList {}

SubjectDataList还有一个 type 属性可以将 type 属性渲染到 rest 请求的 subjectdatas 节点上。

[SerializeAs(Name = "type", Attribute = true)]
public string Type { get; set; } = "array";

然后我创建了一个名为XmlListSerializerwhich implements的类ISerializer。我复制了 XmlSerializer 的实现,但做了一些修改。在该Map方法中,有一部分检查变量rawValue是否为IList. 我稍微改变了这部分,并为我的XmlListSerializer班级添加了一个子句。

所以它现在看起来像这样:

if (propType.IsPrimitive || propType.IsValueType || propType == typeof(string)) {
    //...
} else if (rawValue is IList) {
    ProcessIList((IList) rawValue, element);
} else if (rawValue is ISerializeList) {
    ProcessISerializeList((ISerializeList) rawValue, element);
} else {
    Map(element, rawValue);
}

其中ProcessIListProcessISerializeList定义为:

private void ProcessIList(IList list, XElement element) {
    ProcessIEnumerable(list, element);
}
private void ProcessISerializeList(ISerializeList list, XElement element) {
    ProcessIEnumerable(list, element);
    Map(element, list);
}
private void ProcessIEnumerable(IEnumerable list, XElement element) {
    var itemTypeName = "";
    foreach (var item in list) {
        if (itemTypeName == "") {
            var type = item.GetType();
            var setting = type.GetAttribute<SerializeAsAttribute>();

            itemTypeName = setting != null && setting.Name.HasValue() ? setting.Name : type.Name;
        }

        var instance = new XElement(itemTypeName.AsNamespaced(Namespace));

        Map(instance, item);
        element.Add(instance);
    }
}

我希望这个答案能够帮助其他遇到此问题的人。

于 2017-09-26T15:36:23.580 回答