0

I don't know how to Serialize a object by DataContractSerialize. Here is my code:

    public static string DataContractSerialize(object target)
    {
        var formatter = new DataContractSerializer(target.GetType());
        using (var stream = new MemoryStream())
        {
            formatter.WriteObject(stream, target);
            stream.Position = 0;
            return Encoding.UTF8.GetString(stream.ToArray());
        }
    }

and entity

[Serializable, DataContract(Namespace = "CommunicationModel.Entity")]
[KnownType(typeof(Message))]
[KnownType(typeof(int))]
[KnownType(typeof(string))]
[KnownType(typeof(Type))]
[KnownType(typeof(object))]
public class Message : IDisposable
{
    public Message(string stringInfo)
    {
        MessageValue = stringInfo;
        MessageType = typeof (string);
    }

    public Message(int intInfo)
    {
        MessageValue = intInfo;
        MessageType = typeof (int);
    }
    [DataMember]
    public Type MessageType { get; private set; }
    [DataMember]
    public object MessageValue { get; private set; }

    #region Implementation of IDisposable

    public void Dispose()
    {
    }

    #endregion
}

When I run the DataContractSerialize like this:

var sData = SerializerHelper.DataContractSerialize(msg);

it will throw a exception. What can I do?

rmtheis
  • 5,992
  • 12
  • 61
  • 78
GeminiYellow
  • 1,016
  • 2
  • 12
  • 34
  • It require KnowType Type 'System.RuntimeType' with data contract name 'RuntimeType:http://schemas.datacontract.org/2004/07/System' is not expected. Add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer. – GeminiYellow Apr 20 '12 at 01:11

1 Answers1

0

First, you cannot have a type that is both [Serializable] and [DataContract]. This is not recommended and is meaningless. Just have [DataContract]. For more information on why, see this post on the data contract programming model.

Anyway, the problem here is that you're actually trying to serialize a RuntimeType, because MessageType is represented as a RuntimeType. RuntimeType is an internal class that's a child of Type and that is not public, so that you can't knowingly refer to it as a known type. See What's the difference between System.Type and System.RuntimeType in C#? for more information on what RuntimeType is and why it is the way it is.

So, you have two options here:

  • Consider adding a KnownTypes attribute that takes a static method name. From your static method, you can return the various types you really want, including potentially RuntimeType if you use reflection.

  • The option I'd recommend is to make MessageType a TypeHandle (a RuntimeTypeHandle.) The advantage of this is that you can actually make RuntimeTyepHandle a known type since it's public. It's also serializable and deserializable just like any other type. See this excellent blog post on what I mean.

Community
  • 1
  • 1
krisragh MSFT
  • 1,908
  • 1
  • 13
  • 22