Какой атрибут использовать для сериализации коллекций в WCF? - PullRequest
1 голос
/ 04 марта 2011

У меня есть класс с универсальной коллекцией в качестве свойства, которое я сериализирую с 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 и просто возвращаю коллекцию, то добавление другой коллекции в коллекцию, как ни странно, работает нормально:

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

Я пытался заменить коллекцию списком илиArrayList.Я пытался создать свой собственный производный класс из коллекции.Я пытался использовать комбинации атрибутов DataContract, KnownType, ServiceKnownType и CollectionDataContract, но я либо использую их неправильно, либо у меня возникла другая проблема.

Так есть ли способ добавить коллекции в мою коллекцию в первомНапример, применяя атрибут или используя производный класс?Или есть ли способ сделать это вообще?

1 Ответ

2 голосов
/ 27 мая 2011

Проблема с первым примером состоит в том, что Collection<object> эквивалентен объекту [] - массиву произвольных значений. Вы должны указать WCF, какие значения может содержать коллекция (используя [KnownTypeAttribute] в контракте данных или [ServiceKnownTypeAttribute] в контракте на обслуживание) - даже если этот тип значения равен Collection<object>. Приведенный ниже код работает, когда я добавляю [KnownType (Collection )] к контракту данных.

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...