用于在WCF中序列化集合的属性是什么?

时间:2011-03-04 04:55:44

标签: c# wcf

我有一个带有泛型集合的类作为我正在使用WCF序列化的属性:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    TestObject Load();
}

[DataContract]
public class TestObject
{
    [DataMember]
    public Collection<object> Properties = new Collection<object>();
}

它可以正常工作,直到我将另一个集合添加为集合中的项目(由“坏行”注释表示)

public class Service1 : IService1
{
    public TestObject Load()
    {
        var obj = new TestObject();

        // bad line
        obj.Properties.Add(new Collection<object>());

        return obj;
    }
}

我得到了例外:

System.ServiceModel.CommunicationException:远程服务器返回错误:NotFound。

如果我删除了TestObject类并只返回一个Collection,那么奇怪地将另一个集合添加到集合中就可以了:

[ServiceContract]
public interface IService1
{
    [OperationContract]
    Collection<object> Load();
}

public class Service1 : IService1
{
    public Collection<object> Load()
    {
        Collection<object> coll = new Collection<object>();

        coll.Add(DateTime.Now);
        coll.Add(new Collection<object>() { DateTime.Now, new Collection<object>() });
        coll.Add("sdf");
        coll.Add(99);

        return coll;
    }
}

我尝试用List或ArrayList替换Collection。我试过从Collection创建自己的派生类。我尝试过使用DataContract,KnownType,ServiceKnownType和CollectionDataContract属性的组合,但我要么使用它们不正确,要么我还有其他问题。

那么有没有办法在第一个例子中通过应用属性或使用派生类将集合添加到我的集合中?或者有什么办法可以做到这一点吗?

1 个答案:

答案 0 :(得分:2)

第一个例子的问题是Collection<object>等同于object [] - 一个任意值的数组。您需要告诉WCF集合可以包含哪些值(通过在数据协定上使用[KnownTypeAttribute],或在服务合同上使用[ServiceKnownTypeAttribute]) - 即使此类值为Collection<object>。当我在数据协定上添加[KnownType(Collection&lt; object&gt;)]时,下面的代码可以正常工作。

public class StackOverflow_5189844_751090
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        TestObject Load();
    }
    [DataContract]
    [KnownType(typeof(Collection<object>))]
    public class TestObject
    {
        [DataMember]
        public Collection<object> Properties = new Collection<object>();
    }
    public class Service1 : IService1
    {
        public TestObject Load()
        {
            var obj = new TestObject();

            // bad line
            obj.Properties.Add(new Collection<object>());

            return obj;
        }
    }
    static Binding GetBinding()
    {
        BasicHttpBinding result = new BasicHttpBinding();
        //Change binding settings here
        return result;
    }
    public static void Test()
    {
        string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service1), new Uri(baseAddress));
        host.AddServiceEndpoint(typeof(IService1), GetBinding(), "");
        host.Open();
        Console.WriteLine("Host opened");

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

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

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

在第二种情况下,由于Collection是操作合同的一部分,因此它被认为是该操作的已知类型的一部分,因此不需要显式添加。原始类型(字符串,数字,DateTime)也不需要显式声明,它们已经被WCF“知道”。