Сериализуемый объект для AJAX, WCF и ViewState - PullRequest
0 голосов
/ 30 июня 2010

рассмотрим следующий класс и структуру

public class Entity {
    public IdType Id {get;set;}
    public string Data {get;set;}
}

[TypeConverter(IdTypeConverter))]
public struct IdType {
    ... any data ...
}

IdTypeConverter может преобразовать структуру IdType из и в строку.

Теперь я хочу, чтобы этот класс был сериализуемым для AJAX,WCF и ViewState.Senario может быть веб-службой WCF, которая предоставляет массив данных Entity [] для источника данных.А пользовательский элемент управления, который связывается с источником данных, сохраняет этот класс в его ViewState и отправляет данные в код на стороне клиента.

Этого можно легко достичь, просто добавив атрибут [Serializable] ко всем сериализованным типам.Но я не хочу, чтобы IdType был сериализован, а преобразован в строку.Таким образом, представление JSON должно быть

{ 'Id'=>'StringRepresentationOfId', 'Data'=>'foo' }

. Аналогично, это будет оптимальной сериализацией для WCF и ViewState.

Другое решение - написать другой класс

public class JsonEntity {
    public JsonEntity(Entity from) {
        Id = from.Id;
        Data = from.Data;
    }
    public string Id {get;set;}
    public string Data {get;set;}
}

и использовать его для JsonSerialization.Но мне это не нравится, потому что это означает, что элемент управления, отправляющий данные клиенту, знает о типе сущности.

Фактический вопрос: возможно ли настроить JsonSerialization с атрибутами без прерыванияWCF и сериализация ViewState?

РЕДАКТИРОВАТЬ: ответ типа «Это« невозможно »меня бы удовлетворило, так как я перестал бы пытаться.

Ответы [ 2 ]

1 голос
/ 30 июня 2010

Из того, что я прочитал, класс LosFormatter, используемый для сериализации ViewState, проверяет, существует ли TypeConverter для данного объекта, и использует его, поэтому вам следует ознакомиться с ним.

Эта статья описывает, как создать свой собственный JavaScriptConverter для выполнения настраиваемой сериализации.Метод Serialize, который вы должны реализовать, возвращает IDictionary<string, object>, поэтому вам, возможно, придется создать класс JavaScriptConverter для вашего класса Entity, а не для вашей структуры IdType.Ниже приведен пример, хотя у меня не было возможности проверить его:

Примечание: примеры в моем посте просто ищут связанный TypeConverter для IdType, чтобы преобразовать его в строку, но еслиесть конкретная причина сделать это таким образом, что вы можете просто вызвать определенную функцию (например, переопределить ToString), которая возвращает строковое представление напрямую, а не искать TypeConverter, как это делает мой пример кода.

public class EntityJsonConverter : System.Web.Script.Serialization.JavaScriptConverter
{
    public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
    {
        if (obj == null)
            throw new ArgumentNullException("obj");

        Entity entity = obj as Entity;
        if (entity != null)
        {
            var values = new Dictionary<string, object>();
            TypeConverter idTypeConverter = TypeDescriptor.GetConverter(entity.Id);
            if (idTypeConverter != null)
            {
                if (idTypeConverter.CanConvertTo(typeof(string)))
                    values.Add("Id", idTypeConverter.ConvertTo(entity.Id, typeof(string)));
                else
                    throw new SerializationException(string.Format("The TypeConverter for type \"{0}\" cannot convert to string.", this.GetType().FullName));
            }
            else
                throw new SerializationException(string.Format("Unable to find a TypeConverter for type \"{0}\".", this.GetType().FullName));

            values.Add("Data", serializer.Serialize(entity.Data));

            return values;
        }
        else
            throw new ArgumentException(string.Format("Expected argument of type \"{0}\", but received \"{1}\".", typeof(Entity).FullName, obj.GetType().FullName), "obj");
    }

    public override IEnumerable<Type> SupportedTypes
    {
        get { yield return typeof(Entity); }
    }
}

Если вы также хотите, чтобы поведение, которое вы описали для сериализации XML, могло бы иметь структуру IdType, реализующую интерфейс IXmlSerializable.Ниже приведен пример реализации метода WriteXml, который использует TypeConverter, определенный для структуры IdType:

    void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer)
    {
        TypeConverter converter = TypeDescriptor.GetConverter(this);
        if (converter != null)
        {
            if (converter.CanConvertTo(typeof(string)))
                writer.WriteString(converter.ConvertTo(this, typeof(string)) as string);
            else
                throw new SerializationException(string.Format("The TypeConverter for type \"{0}\" cannot convert to string.", this.GetType().FullName));
        }
        else
            throw new SerializationException(string.Format("Unable to find a TypeConverter for type \"{0}\".", this.GetType().FullName));
    }
1 голос
/ 30 июня 2010

Другое решение, подобное созданию прокси-класса только для сериализации, - использование атрибута [NonSerialized()].

IdType может быть не сериализуемым, а другое свойство сериализуемой строки может быть реализовано как прокси-сервер (который при получении или установке - назначает / читает из IdType).даже выглядеть элегантно с использованием аспектно-ориентированного программирования.

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