【问题标题】:Convert CookComputing XMLRpcStruct (IEnumerable<Object>) to an actual C# class将 CookComputing XMLRpcStruct (IEnumerable<Object>) 转换为实际的 C# 类
【发布时间】:2017-02-27 06:28:43
【问题描述】:

所以,我正在使用 CookComputings XMLRPC 库来与 InfusionSoft 交谈(这是一个非常流行的在线 CRM)。主要方法是:

 [XmlRpcMethod("DataService.query")]
 IEnumerable<object> QuerySubscriptionStatus(string apiKey, 
        string table, int limit, int page, 
        IDictionary queryData, string[] selectedFields);

遗憾的是,我需要使用IEnumerable&lt;object&gt;,因为 InfusionSoft XML/RPC API 需要它。我希望不是这样,但很遗憾是这样。

由于我使用 .NET 4.5,我想我可以做一个动态转换:

  var subStatus = proxy.QuerySubscriptionStatus(
      _key, "RecurringOrder", 500, 0, dict, sarray);
  var result = subStatus.Cast<SubscriptionStatus>();

不幸的是,这不起作用,我收到了来自 C# 的一个非常令人沮丧的错误:

无法将“CookComputing.XmlRpc.XmlRpcStruct”类型的对象转换为“WBI.Model.SubscriptionStatus”类型。`

我尝试将我的班级指定为struct;哎呀,我什至尝试使用XMLRpcMember() 标签指定它,但不,它只是不会转换。

如何与IEnumerable 中的数据进行交互?

我尝试过的类/结构类型

public struct SubStatus
{
    public int AffiliateId;
    public int AutoCharge;
    public double BillingAmt;
    public string BillingCycle;
    public int CC1;
    public int CC2;
    public int ContactId;
    public DateTime EndDate;
    public int Frequency;
    public int Id;
    public DateTime LastBillDate;
    public int LeadAffiliateId;
    public int MaxRetry;
    public int MerchantAccountId;
    public DateTime NextBillDate;
    public int NumDaysBetweenRetry;
    public int OriginatingOrderId;
    public DateTime PaidThruDate;
    public int PaymentGatewayId;
    public int ProductId;
    public int ProgramId;
    public string PromoCode;
    public int Qty;
    public string ReasonStopped;
    public int ShippingOptionId;
    public DateTime StartDate;
    public string Status;
    public int SubscriptionPlanId;
}

我还尝试了一个带有XMLRpcMember 标签的简单类:

public class SubscriptionStatus
{
    [XmlRpcMember("AffiliateId")]
    public int AffiliateId { get; set; }
    [XmlRpcMember("AutoCharge")]
    public int AutoCharge { get; set; }
    [XmlRpcMember("BillingAmt")]
    public double BillingAmt { get; set; }
    [XmlRpcMember("BillingCycle")]
    public string BillingCycle { get; set; }
    [XmlRpcMember("CC1")]
    public int CC1 { get; set; }
    [XmlRpcMember("CC2")]
    public int CC2 { get; set; }
    [XmlRpcMember("ContactId")]
    public int ContactId { get; set; }
    [XmlRpcMember("EndDate")]
    public DateTime EndDate { get; set; }
    [XmlRpcMember("Frequency")]
    public int Frequency { get; set; }
    [XmlRpcMember("Id")]
    public int Id { get; set; }
    [XmlRpcMember("LastBillDate")]
    public DateTime LastBillDate { get; set; }
    [XmlRpcMember("LeadAffiliateId")]
    public int LeadAffiliateId { get; set; }
    [XmlRpcMember("MaxRetry")]
    public int MaxRetry { get; set; }
    [XmlRpcMember("MerchantAccountId")]
    public int MerchantAccountId { get; set; }
    [XmlRpcMember("NextBillDate")]
    public DateTime NextBillDate { get; set; }
    [XmlRpcMember("NumDaysBetweenRetry")]
    public int NumDaysBetweenRetry { get; set; }
    [XmlRpcMember("OriginatingOrderId")]
    public int OriginatingOrderId { get; set; }
    [XmlRpcMember("PaidThruDate")]
    public DateTime PaidThruDate { get; set; }
    [XmlRpcMember("PaymentGatewayId")]
    public int PaymentGatewayId { get; set; }
    [XmlRpcMember("ProductId")]
    public int ProductId { get; set; }
    [XmlRpcMember("ProgramId")]
    public int ProgramId { get; set; }
    [XmlRpcMember("PromoCode")]
    public string PromoCode { get; set; }
    [XmlRpcMember("Qty")]
    public int Qty { get; set; }
    [XmlRpcMember("ReasonStopped")]
    public string ReasonStopped { get; set; }
    [XmlRpcMember("ShippingOptionId")]
    public int ShippingOptionId { get; set; }
    [XmlRpcMember("StartDate")]
    public DateTime StartDate { get; set; }
    [XmlRpcMember("Status")]
    public string Status { get; set; }
    [XmlRpcMember("SubscriptionPlanId")]
    public int SubscriptionPlanId { get; set; }
}

【问题讨论】:

    标签: c# .net .net-4.5 xml-rpc


    【解决方案1】:

    因此,在另一位高级开发人员的帮助下,事实证明我们能够对结构进行一些更改:

        private string[] retFlds = { "Id", "ContactId", "OriginatingOrderId", "ProgramId", "SubscriptionPlanId", "ProductId", "StartDate", "NextBillDate", "BillingCycle", "Frequency", "BillingAmt", "Status", "ReasonStopped", "AutoCharge", "CC1", "CC2", "NumDaysBetweenRetry", "MaxRetry", "MerchantAccountId", "AffiliateId", "PromoCode", "LeadAffiliateId", "Qty", "ShippingOptionId" };
        private string table = "RecurringOrder";
        private DataTable dt = new DataTable();
        // here's the query 
        XmlRpcStruct[] retData = proxy.Query(Auth.key, table, 1000, 0, qryData, returnFields);
        dt = StructArrayToDT(retData);
    
        public static DataTable StructArrayToDT(XmlRpcStruct[] data)
        {
            DataTable dt = new DataTable();
            if (data.Length == 0) { return dt; }
    
            // do columns
            foreach (DictionaryEntry d in data[0])
            {
                dt.Columns.Add(d.Key.ToString(), typeof(object));
            }
    
            foreach (XmlRpcStruct xmlstruct in data)
            {
                DataRow dr = dt.NewRow();
                foreach (DictionaryEntry d in xmlstruct)
                {
                    try
                    {
                        dr[d.Key.ToString()] = d.Value;
                    }
                    catch (Exception ex)
                    { 
                        // handle errors
                    }
    
                }
                dt.Rows.Add(dr);
            }
            return dt;
        }
    

    现在终于可以毫无问题地访问该数据了。

    【讨论】:

      【解决方案2】:

      查看 QuerySubscriptionStatus 的签名及其返回的 IEnumerable。如果您再次查看正在实现 IDictionary、ICollection、IEnumerable 的 XmlRpcStruct (Fork of XML.Rpc.Net) 的定义。因此,如果我们假设 QuerySubscriptionStatus 返回实现 IEnumerable 的 XmlRpcStruct ,那么您将获得 Enumeration 作为响应,它本质上是项目的集合(即使它包含单个项目)。您正在尝试将枚举类型转换为不是集合的结构 (SubscriptionStatus)。因此错误。 如果 Enumeration 中包含的项目属于 SubscriptionStatus 结构类型,那么下面的行应该可以解决问题。

      var resultList = subStatus.ToList<SubscriptionStatus();
      

      然后遍历 resultList 以访问来自 QuerySubscriptionStatus 方法的响应。

      foreach(var result in resultList)
      {
      
      }
      

      或者,如果您确定响应列表将只有一个条目,那么您也可以使用以下

      var result = resultList.FirstOrDefault();
      

      希望对您有所帮助。

      【讨论】:

      • 不幸的是,将其转换为 List 是不可能的,因为 IEnumerable 不允许这样做。这是一段令人沮丧的旅程,哈哈谢谢你的建议:)Compiler Error Message: CS1929: 'IEnumerable&lt;object&gt;' does not contain a definition for 'ToList' and the best extension method overload 'Enumerable.ToList&lt;SubscriptionStatus&gt;(IEnumerable&lt;SubscriptionStatus&gt;)' requires a receiver of type 'IEnumerable&lt;SubscriptionStatus&gt;'
      猜你喜欢
      • 2012-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多