2013-03-18 49 views
2

我有問題。哈希表如何在WCF中工作?

考慮下面

IService1.cs

[ServiceContract] 
public interface IService1 
{ 


    [OperationContract] 
    Hashtable GetHashTableCollection(); 


    [OperationContract] 
    List<A> GetARecords(); 


} 

[DataContract] 
public class A 
{ 
    [DataMember] 
    public int MyProperty { get; set; } 

    [DataMember] 
    public Hashtable MyTable { get; set; } 
} 

Service1.cs

public class Service1 : IService1 
    { 
     public Hashtable GetHashTableCollection() 
     { 
      Hashtable hashtable = new Hashtable(); 
      hashtable.Add("Area", 1000); 
      hashtable.Add("Perimeter", 55); 
      hashtable.Add("Mortgage", 540); 
      return hashtable; 
     } 

     public List<A> GetARecords() 
     { 
      List<A> Alist = new List<A>(); 
      Alist.Add(new A { MyProperty = 1, MyTable = GetHashTableCollection() }); 
      Alist.Add(new A { MyProperty = 2, MyTable = GetHashTableCollection() }); 

      return Alist; 
     } 
    } 

和客戶機應用是作爲下

private void button1_Click(object sender, EventArgs e) 
{ 
    ServiceReference1.Service1Client sc = new ServiceReference1.Service1Client(); 
    var r1 = sc.GetHashTableCollection(); 
    var r2 = sc.GetARecords(); 
} 

它工作正常,沒有任何問題。 HashTable已被轉換爲Dictionary對象。

我的印象是,因爲HashTable使用IDictionary,所以它應該在編譯時失敗(發生在3.5)。

無法隱式轉換類型 'System.Collections.Generic.Dictionary' 到 'System.Collections.Hashtable'

但是,它的工作。怎麼樣?

我是否缺少任何基本概念?或者DataContractSerializer正在做這項工作?或者在dot.net 4.0中改變了一些東西?

它是什麼以及它爲什麼工作?

回答

1

它基於IDictionary。 WCF將IDictionary視爲Dictionary<object, object>,它在WSDL上公開。你可以有一個自定義的類實現IDictionary,並且行爲將是相同的。例如,如果您運行以下任一項目,並使用svcutil或添加服務引用來爲該服務生成代理(您有IDictionary類型),則您將在客戶端中獲得Dictionary<object, object>

public class StackOverflow_15471185 
{ 
    [ServiceContract] 
    public interface IService1 
    { 
     [OperationContract] 
     Hashtable GetHashTableCollection(); 
     [OperationContract] 
     List<A> GetARecords(); 
    } 

    [DataContract] 
    public class A 
    { 
     [DataMember] 
     public int MyProperty { get; set; } 

     [DataMember] 
     public Hashtable MyTable { get; set; } 
    } 

    public class Service : IService1 
    { 
     public Hashtable GetHashTableCollection() 
     { 
      Hashtable hashtable = new Hashtable(); 
      hashtable.Add("Area", 1000); 
      hashtable.Add("Perimeter", 55); 
      hashtable.Add("Mortgage", 540); 
      return hashtable; 

     } 

     public List<A> GetARecords() 
     { 
      List<A> Alist = new List<A>(); 
      Alist.Add(new A { MyProperty = 1, MyTable = GetHashTableCollection() }); 
      Alist.Add(new A { MyProperty = 2, MyTable = GetHashTableCollection() }); 

      return Alist; 
     } 
    } 

    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), ""); 
     host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     var factory = new ChannelFactory<IService1>(new BasicHttpBinding(), new EndpointAddress(baseAddress)); 
     var proxy = factory.CreateChannel(); 
     Console.WriteLine(proxy.GetHashTableCollection()); 

     ((IClientChannel)proxy).Close(); 
     factory.Close(); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
} 

public class StackOverflow_15471185_b 
{ 
    [ServiceContract] 
    public interface IService1 
    { 
     [OperationContract] 
     MyDic GetHashTableCollection(); 
     [OperationContract] 
     List<A> GetARecords(); 
    } 

    public class MyDic : IDictionary 
    { 
     public IDictionary dic = new Hashtable(); 

     public void Add(object key, object value) 
     { 
      dic.Add(key, value); 
     } 

     public void Clear() 
     { 
      dic.Clear(); 
     } 

     public bool Contains(object key) 
     { 
      return dic.Contains(key); 
     } 

     public IDictionaryEnumerator GetEnumerator() 
     { 
      return dic.GetEnumerator(); 
     } 

     public bool IsFixedSize 
     { 
      get { return dic.IsFixedSize; } 
     } 

     public bool IsReadOnly 
     { 
      get { return dic.IsReadOnly; } 
     } 

     public ICollection Keys 
     { 
      get { return dic.Keys; } 
     } 

     public void Remove(object key) 
     { 
      dic.Remove(key); 
     } 

     public ICollection Values 
     { 
      get { return dic.Values; } 
     } 

     public object this[object key] 
     { 
      get 
      { 
       return dic[key]; 
      } 
      set 
      { 
       dic[key] = value; 
      } 
     } 

     public void CopyTo(Array array, int index) 
     { 
      dic.CopyTo(array, index); 
     } 

     public int Count 
     { 
      get { return dic.Count; } 
     } 

     public bool IsSynchronized 
     { 
      get { return dic.IsSynchronized; } 
     } 

     public object SyncRoot 
     { 
      get { return dic.SyncRoot; } 
     } 

     IEnumerator IEnumerable.GetEnumerator() 
     { 
      return ((IEnumerable)dic).GetEnumerator(); 
     } 
    } 

    [DataContract] 
    public class A 
    { 
     [DataMember] 
     public int MyProperty { get; set; } 

     [DataMember] 
     public MyDic MyTable { get; set; } 
    } 

    public class Service : IService1 
    { 
     public MyDic GetHashTableCollection() 
     { 
      MyDic hashtable = new MyDic(); 
      hashtable.Add("Area", 1000); 
      hashtable.Add("Perimeter", 55); 
      hashtable.Add("Mortgage", 540); 
      return hashtable; 

     } 

     public List<A> GetARecords() 
     { 
      List<A> Alist = new List<A>(); 
      Alist.Add(new A { MyProperty = 1, MyTable = GetHashTableCollection() }); 
      Alist.Add(new A { MyProperty = 2, MyTable = GetHashTableCollection() }); 

      return Alist; 
     } 
    } 

    public static void Test() 
    { 
     string baseAddress = "http://" + Environment.MachineName + ":8000/Service"; 
     ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress)); 
     host.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), ""); 
     host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 
     host.Open(); 
     Console.WriteLine("Host opened"); 

     var factory = new ChannelFactory<IService1>(new BasicHttpBinding(), new EndpointAddress(baseAddress)); 
     var proxy = factory.CreateChannel(); 
     Console.WriteLine(proxy.GetHashTableCollection()); 

     ((IClientChannel)proxy).Close(); 
     factory.Close(); 

     Console.Write("Press ENTER to close the host"); 
     Console.ReadLine(); 
     host.Close(); 
    } 
}