2

我有个问题。

考虑以下

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

服务1.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 发生了一些变化?

它是什么以及它为什么起作用?

4

1 回答 1

1

它基于IDictionary. WCF 将 IDictionary 视为 aDictionary<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();
    }
}
于 2013-03-18T23:44:24.783 回答