WCF.list被反序列化为数组.如何使它成为任何可写列表(ArrayList)

本文关键字:列表 任何可 ArrayList 何使它 list 反序列化 数组 WCF | 更新日期: 2023-09-27 18:16:58

我有一个客户端-服务器应用程序,其中各部分通过WCF (netttcp绑定)相互"通信"。

我有我的数据合约,它有一个第三方类的1个字段:

[Serializable]
public class MyResult{
  public ThirdPartyResult Result {get;set;}
  /* other fields */
}

使用反射,我看到如下:

[Serializable]
public class ThirdPartyResult {
  private IList result;
  public IList Result
  { 
    get { return result ?? (result = new ArrayList());}
  }
}

当从客户端调用服务器时,我将result作为服务器上的ArrayList。到达客户端后,result字段变成固定大小的数组。

没有使用添加服务引用,但我使用汇编共享,只是做

ChannelFactory<IMyContract>.CreateChannel(new NetTcpBinding("Configuration.Name"), address);

UPDATE:服务合同

[ServiceContract]
[ServiceKnownType(typeof(ArrayList))]
[ServiceKnownType(typeof(ThirdPartyResult))]
public interface IMyContract
{
   MyResult GetResult();
}

现在的问题是:
我如何告诉WCF使用ArrayList而不是Array ?


我想出了一个非常糟糕的解决方案(从我的角度来看)
一般来说,我想要一个ArrayList被保留,以便能够添加项目到它。最后,我想出了下面的解决方案。是的,我知道,这是完全糟糕的,这就是为什么我还在寻找一些更好的变体。

        if (thirdParty.Results != null && thirdParty.Results.IsFixedSize)
        {
            var results = new ArrayList(thirdParty.Results);
            // Finding result by ReferenceEquals to not be tight to private variable name
            var resultsField = thirdParty.GetType()
                .GetFields(BindingFlags.Default | BindingFlags.Instance | BindingFlags.NonPublic)
                .Where(f => ReferenceEquals(f.GetValue(thirdParty), thirdParty.Results))
                .FirstOrDefault();
            if (resultsField != null)
                resultsField.SetValue(thirdParty, results);
        }
        thirdParty.AddResult(otherChild);

WCF.list被反序列化为数组.如何使它成为任何可写列表(ArrayList)

当你在Visual Studio中创建一个新的服务引用(或配置一个现有的引用)时,有一个类似于"将数组反序列化为"的属性,在那里你可以选择array/list/等等。您可以查看生成的代码,并更改代码以达到您想要的效果。

请参阅以下内容:

WCF:序列化和反序列化泛型集合

这解决了我的问题:私有成员和自定义属性方法都为我工作。

[DataMember]
private List<Person> members = new List<Person>();

或者将属性更改为:

[DataMember]
private Iist<Person> members = new Iist<Person>();
[DataMember()]
public IList<Person> Feedback {
    get { return m_Feedback; }
    set {
        if ((value != null)) {
            m_Feedback = new List<Person>(value);
        } else {
            m_Feedback = new List<Person>();
        }
    }
}

最终,您的合约不包含会使它选择任何特定实现的信息。解决这个问题的最好办法是;使result类型良好,例如ArrayList:

private ArrayList result;
public IList Result { 
  get { return result ?? (result = new ArrayList());}
}

个人我希望看到List<T>[DataContract]/[DataMember]等,但是…

如果没有别的,那么我会写一个扩展类来扩展ThirdPartyResult

 public static class ThirdPartyResultExtension
  {
    public static ArrayList ResultsAsArrayList(this ThirdPartyResult d)
    {
      ArrayList list = new ArrayList();
      list.AddRange(d.Result);
      return list;
    }
  }
  public class ThirdPartyResult
  {
    private IList result;
    public IList Result
    {
      get { return result ?? (result = new ArrayList()); }
    }
  }

,像

一样使用
 ThirdPartyResult r;
     ArrayList arrlist = r.ResultsAsArrayList();