简体   繁体   English

可序列化为AJAX,WCF和ViewState的对象

[英]Object serializable for AJAX, WCF and ViewState

consider the following class and struct 考虑以下类和结构

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

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

The IdTypeConverter can convert the IdType struct from and to string. IdTypeConverter可以将IdType结构从一个字符串转换为另一个字符串。

Now, what I want is this class to be serializable for AJAX, WCF and ViewState. 现在,我想要的是该类可针对AJAX,WCF和ViewState进行序列化。 The senario could be a WCF web service which provides as array of Entity[] to a DataSource. 该传感器可以是WCF Web服务,它作为Entity []数组提供给数据源。 And a custom control which binds to the datasource, saves this class to it's ViewState and sends the data to client side code. 还有一个绑定到数据源的自定义控件,将该类保存到它的ViewState并将数据发送到客户端代码。

This could be achieved easily by simply adding a [Serializable] attribute to all serialized types. 只需将[Serializable]属性添加到所有序列化类型即可轻松实现。 But I don't want the IdType to be serialized, but to be converted to a string. 但是我不希望将IdType序列化,而是将其转换为字符串。 Thus the JSON representation should be 因此,JSON表示应为

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

This would analogously be the optimal serialization for WCF and ViewState. 类似地,这将是WCF和ViewState的最佳序列化。

Another solution would be to write another class 另一个解决方案是编写另一个类

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

and use this for JsonSerialization. 并将其用于JsonSerialization。 But I don't like this, because this would imply that the control which is sending the data to the client knows about the Entity type. 但是我不喜欢这样,因为这意味着将数据发送到客户端的控件知道实体类型。

The actual question is: Is it possible to customize JsonSerialization with attributes without breaking WCF and ViewState serialization? 实际的问题是:是否可以在不破坏WCF和ViewState序列化的情况下使用属性自定义JsonSerialization?

EDIT: An answer like "That' impossible" would satify me, since I'd stop trying. 编辑:像“那不可能”的答案会让我满意,因为我会停止尝试。

Another solution similar to creating a proxy class just for serialization would be using the [NonSerialized()] attribute. 类似于创建仅用于序列化的代理类的另一种解决方案是使用[NonSerialized()]属性。

IdType could be non-serializable and another serializable string property could be implemented as a proxy (which would - on get or set - assign to / read from the IdType). IdType可以是不可序列化的,而另一个可序列化的字符串属性可以作为代理实现(将在获取或设置时分配给IdType或从中读取)。

The solution could even look elegant with the use of aspect-oriented programming. 通过使用面向方面的编程,该解决方案甚至可以看起来很优雅。

From what I've read, the LosFormatter class used for ViewState serialization checks if there is a TypeConverter for a given object and uses it, so you should be covered there. 从我阅读的内容来看,用于ViewState序列化的LosFormatter类检查给定对象是否存在TypeConverter并使用它,因此应该在此处进行介绍。

This article describes how to create your own JavaScriptConverter to perform custom serialization. 本文介绍如何创建自己的JavaScriptConverter来执行自定义序列化。 The Serialize method that you have to implement returns IDictionary<string, object> , so you might have to create a JavaScriptConverter class for your Entity class rather than for your IdType struct. 您必须实现的Serialize方法返回IDictionary<string, object> ,因此您可能必须为Entity类而不是IdType结构创建一个JavaScriptConverter类。 Below is an example, though I haven't had a chance to test it out: 下面是一个示例,尽管我没有机会对其进行测试:

Note: the examples in my post just look up the associated TypeConverter for IdType in order to convert it to a string, but unless there's a specific reason to do it that way you might as well just call a specific function (eg override ToString) that returns a the string representation directly instead of looking up the TypeConverter as my example code is doing. 注意:我的帖子中的示例只是查找关联的IdType的TypeConverter以便将其转换为字符串,但是除非有特定原因这样做,否则您最好只调用一个特定的函数(例如,覆盖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); }
    }
}

If you also want the behavior that you described for XML serialization, you could have the IdType struct implement the IXmlSerializable interface. 如果还希望描述XML序列化的行为,则可以让IdType结构实现IXmlSerializable接口。 Below is an example of a WriteXml method implementation that uses the TypeConverter defined for the IdType struct: 下面是使用为IdType结构定义的TypeConverter的WriteXml方法实现的示例:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM