Атрибут не включен в сгенерированный прокси-класс

Использование .Net 3.0 и VS2005.

Рассматриваемые объекты потребляются из службы WCF, а затем сериализуются обратно в XML для устаревшего API. Таким образом, вместо сериализации TestObject, он сериализовал .TestObject, в котором отсутствовал атрибут [XmlRoot]; однако все атрибуты [Xml *] для дочерних элементов были в сгенерированном коде прокси, поэтому они работали нормально. Таким образом, все дочерние элементы работали нормально, но не включающий элемент, потому что атрибут [XmlRoot] не был включен в сгенерированный код прокси. Исходный объект, включающий атрибут [XmlRoot], отлично сериализуется вручную.

Могу ли я включить в прокси-код атрибут [XmlRoot], чтобы сгенерированный прокси-класс также правильно сериализовался? Если я не могу этого сделать, я подозреваю, что мне придется использовать [XmlType], но это вызовет незначительный ущерб, требующий от меня изменения других компонентов, поэтому я бы предпочел первый. Я также хочу избежать необходимости вручную редактировать автоматически созданный прокси-класс.

Вот пример кода (я включил клиент и службу в одно приложение, потому что это быстро и для тестовых целей. Закомментируйте код ссылки службы и добавьте ссылку на службу при запуске приложения, затем раскомментируйте код службы и запустите .)

namespace SerializationTest {  
  class Program {  
    static void Main( string[] args ) {  

        Type serviceType = typeof( TestService );  
        using (ServiceHost host = new ServiceHost(   
            serviceType,   
            new Uri[] {   
                new Uri( "http://localhost:8080/" )  
            }  

        ))
        {

            ServiceMetadataBehavior behaviour = new ServiceMetadataBehavior();  
            behaviour.HttpGetEnabled = true;  
            host.Description.Behaviors.Add( behaviour );  

            host.AddServiceEndpoint( serviceType, new BasicHttpBinding(), "TestService" );  
            host.AddServiceEndpoint( typeof( IMetadataExchange ), new BasicHttpBinding(), "MEX" );  


            host.Open();  

            TestServiceClient client = new TestServiceClient();  
            localhost.TestObject to = client.GetObject();  

            String XmlizedString = null;  
            using (MemoryStream memoryStream = new MemoryStream()) {
                XmlSerializer xs = new XmlSerializer( typeof( localhost.TestObject ) );  
                using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream)) {
                    xs.Serialize( xmlWriter, to );  
                    memoryStream = (MemoryStream)xmlWriter.BaseStream;  
                    XmlizedString = Encoding.UTF8.GetString( memoryStream.ToArray() );  
                    Console.WriteLine( XmlizedString );  
                }    
            }    
        }

        Console.ReadKey();  
    }  
}  

[Serializable]  
[XmlRoot( "SomethingElse" )]  
public class TestObject {  

    private bool _worked;  

    public TestObject() { Worked = true; }  

    [XmlAttribute( AttributeName = "AttributeWorked" )]  
    public bool Worked {  
        get { return _worked; }  
        set { _worked = value; }  
    }  
}  

[ServiceContract]  
public class TestService {  

    [OperationContract]  
    [XmlSerializerFormat]  
    public TestObject GetObject() {  
        return new TestObject();  
    }  
  }  
}  

Вот генерируемый XML-код.

<?xml version = "1.0" encoding = "utf-8"?>
<TestObject xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" AttributeWorked = "true" /> 

Вы контролируете схему xsd, которая используется для создания прокси?

hurst 03.10.2008 05:40

Я не удивлен, что XmlRoot не создается. Что мне кажется странным, так это то, что сгенерированный класс не называется SomethingElse. Вы сгенерировали прокси после добавления атрибута XmlRoot?

csgero 07.10.2008 12:31

Я считаю, что нужно избегать изменения схемы / сгенерированного прокси. Просто используйте их для получения, затем развернитесь и снова отправьте на сторону с наследием. Но было бы неплохо не писать новый набор определений - отсюда желание переименовывать на лету. Я предложил использовать XmlAttributeOverrides.

hurst 09.10.2008 04:58
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
3
3 425
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я нашел человека, который предоставляет средства для решения этой ситуации:

Блог Матевза Гацника

Используя этот подход XmlAttributeOverrides, я написал следующее:

    private static XmlSerializer GetOverridedSerializer()
    {
        // set overrides for TestObject element
        XmlAttributes attrsTestObject = new XmlAttributes();
        XmlRootAttribute rootTestObject = new XmlRootAttribute("SomethingElse");
        attrsTestObject.XmlRoot = rootTestObject;

       // create overrider
       XmlAttributeOverrides xOver = new XmlAttributeOverrides();
       xOver.Add(typeof(localhost.TestObject), attrsTestObject);

       XmlSerializer xSer = new XmlSerializer(typeof(localhost.TestObject), xOver);
       return xSer;
    }

Просто поместите этот метод в класс Program вашего примера и замените следующую строку в Main():

        //XmlSerializer xs = new XmlSerializer(typeof(localhost.TestObject));
        XmlSerializer xs = GetOverridedSerializer();

А потом бегите смотреть результаты.

Вот что у меня получилось:

<?xml version = "1.0" encoding = "utf-8"?><SomethingElse xmlns:xsi = "http://www.w3.o
rg/2001/XMLSchema-instance" xmlns:xsd = "http://www.w3.org/2001/XMLSchema" Attribu
teWorked = "true" />

Я думаю, проблема не в использовании XmlSerializer, а в коде, созданном для прокси. В реальном сценарии сериализацией XML будет заниматься WCF, поэтому вы не можете напрямую влиять на используемый XmlSerializer.

csgero 08.10.2008 19:36

Верно. Но суть в том, чтобы иметь возможность перепрофилировать контракт данных, не изменяя его физически (регенерируя или редактируя вручную) и, таким образом, не мешая первоначальному намерению использовать его с WCF.

hurst 09.10.2008 04:51

Извините, вы правы, я упустил суть. Существует также несколько более простое решение, использующее конструктор XmlSerializer, который принимает параметр XmlRootAttribute.

csgero 10.10.2008 16:34

Для моей проблемы эти переопределения были бы слишком распространены, поэтому я не думаю, что это решение именно то, что мне нужно. Я также думаю, что когда мы перейдем к 2008 году и начнем делиться типами, это уже не будет иметь значения. Поэтому, хотя я не использую это, я отмечу это как ответ.

vfilby 10.10.2008 19:41

== ЕСЛИ ==

Это только для атрибута XmlRoot. XmlSerializer имеет один конструктор, в котором вы можете указать атрибут XmlRoot.

Престижность csgero за указание на нее. Его комментарий должен стать решением.

XmlSerializer Constructor (Type, XmlRootAttribute)

Initializes a new instance of the XmlSerializer class that can serialize objects of the specified type into XML documents, and deserialize an XML document into object of the specified type. It also specifies the class to use as the XML root element.

Плохой конструктор. Созданная сборка сериализатора Xml не кэшируется.

mark 12.07.2016 00:38

Другие вопросы по теме