简体   繁体   English

转换 CookComputing XMLRpcStruct (IEnumerable<Object> ) 到实际的 C# 类

[英]Convert CookComputing XMLRpcStruct (IEnumerable<Object>) to an actual C# class

So, I am using CookComputings XMLRPC library to be able to talk to InfusionSoft (it's an online CRM that's quite popular).因此,我正在使用 CookComputings XMLRPC库来与InfusionSoft (它是一个非常流行的在线 CRM)对话。 The main method is:主要方法是:

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

I am REQUIRED to use an IEnumerable<object> sadly, as the InfusionSoft XML/RPC API requires it.遗憾的是,我需要使用IEnumerable<object> ,因为 InfusionSoft XML/RPC API 需要它。 I wish it wasn't the case, but sadly it is.我希望不是这样,但遗憾的是。

Since I use .NET 4.5, I figured I can just do a dynamic cast:由于我使用 .NET 4.5,我想我可以做一个动态转换:

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

Unfortunately, this doesn't work, I'm given a very upset error from C#:不幸的是,这不起作用,我从 C# 中得到了一个非常令人沮丧的错误:

Unable to cast object of type 'CookComputing.XmlRpc.XmlRpcStruct' to type 'WBI.Model.SubscriptionStatus'.`无法将“CookComputing.XmlRpc.XmlRpcStruct”类型的对象转换为“WBI.Model.SubscriptionStatus”。`

I've tried specifying my class as a struct ;我试过将我的类指定为struct heck I've even tried specifying it with XMLRpcMember() tags, but nope, it just wont convert. XMLRpcMember()我什至尝试用XMLRpcMember()标签指定它,但不,它只是不会转换。

How can I interact with the data in the IEnumerable ?如何与IEnumerable的数据进行交互?

Class/Struct Types I've Tried我尝试过的类/结构类型

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

I also just tried a simple class with the XMLRpcMember tags:我也只是尝试了一个带有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; }
}

So, after some extended help from another senior developer, it turns out we were able to make some changes to the struct:因此,经过另一位高级开发人员的一些扩展帮助,结果证明我们能够对结构进行一些更改:

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

Finally can access that data without any issue now.现在终于可以毫无问题地访问该数据了。

Looking at signature of QuerySubscriptionStatus its returning IEnumerable.查看 QuerySubscriptionStatus 其返回的 IEnumerable 的签名。 Again if you look at definition of XmlRpcStruct ( Fork of XML.Rpc.Net ) which is implementing IDictionary, ICollection, IEnumerable.同样,如果您查看实现 IDictionary、ICollection、IEnumerable 的 XmlRpcStruct(XML.Rpc.Net 的Fork )的定义。 So if we assume that QuerySubscriptionStatus is returning XmlRpcStruct which implements IEnumerable then you are getting Enumeration in response which is essentially collection of items (even if it contains single item).因此,如果我们假设 QuerySubscriptionStatus 正在返回实现 IEnumerable 的 XmlRpcStruct,那么您将获得 Enumeration 作为响应,它本质上是项目的集合(即使它包含单个项目)。 You are trying to typecast Enumeration to structure (SubscriptionStatus) which is not collection.您正在尝试将枚举类型转换为不是集合的结构 (SubscriptionStatus)。 Hence the error.因此错误。 If items contained in Enumeration are of type SubscriptionStatus structure then following line should do trick.如果包含在 Enumeration 中的项目属于 SubscriptionStatus 结构类型,那么以下行应该可以解决问题。

var resultList = subStatus.ToList<SubscriptionStatus();

and then loop through resultList to access response from QuerySubscriptionStatus method.然后循环遍历 resultList 以访问来自 QuerySubscriptionStatus 方法的响应。

foreach(var result in resultList)
{

}

OR if you are sure that response list will have single entry then you may also use following或者,如果您确定响应列表只有一个条目,那么您也可以使用以下内容

var result = resultList.FirstOrDefault();

Hope that helps.希望有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM