visual studio sirve que para c# serialization reflection datacontract

c# - studio - Excepción de serialización de DataContract(no se espera el nombre del contrato de datos)



reference datacontract (1)

Tengo el siguiente código:

[DataContract] class TestContract { private String _Name; private Int32 _Age; [DataMember( Name = "Name" )] public String Name { get { return _Name; } set { _Name = value; } } [DataMember( Name = "Age" )] public Int32 Age { get { return _Age; } set { _Age = value; } } } [Serializable] public class DNCJsonDictionary<K, V> : ISerializable { Dictionary<K, V> dict = new Dictionary<K, V>(); public DNCJsonDictionary() { } protected DNCJsonDictionary( SerializationInfo info, StreamingContext context ) { } public void GetObjectData( SerializationInfo info, StreamingContext context ) { foreach( K key in dict.Keys ) { info.AddValue( key.ToString(), dict[ key ] ); } } public void Add( K key, V value ) { dict.Add( key, value ); } public V this[ K index ] { set { dict[ index ] = value; } get { return dict[ index ]; } } } public class MainClass { public static String Serialize( Object data ) { var serializer = new DataContractJsonSerializer( data.GetType() ); var ms = new MemoryStream(); serializer.WriteObject( ms, data ); return Encoding.UTF8.GetString( ms.ToArray() ); } public static void Main() { DNCJsonDictionary<String, Object> address = new DNCJsonDictionary<String, Object>(); address[ "Street" ] = "30 Rockefeller Plaza"; address[ "City" ] = "New York City"; address[ "State" ] = "NY"; TestContract test = new TestContract(); test.Name = "CsDJ"; test.Age = 28; DNCJsonDictionary<String, Object> result = new DNCJsonDictionary<String, Object>(); result[ "foo" ] = "bar"; result[ "Name" ] = "John Doe"; result[ "Age" ] = 32; result[ "Address" ] = address; // ** --- THIS THROWS AN EXCEPTION!!! --- ** result[ "test" ] = test; Console.WriteLine( Serialize( result ) ); Console.ReadLine(); } }

Cuando corro, obtengo esta excepción:

Escriba ''Json_Dictionary_Test.TestContract'' con el nombre del contrato de datos ''TestContract: http://schemas.datacontract.org/2004/07/Json_Dictionary_Test '' no se espera. Agregue cualquier tipo no conocido de forma estática a la lista de tipos conocidos, por ejemplo, utilizando el atributo KnownTypeAttribute o agregándolos a la lista de tipos conocidos pasados ​​a DataContractSerializer.

¡Pero no entiendo eso! Como sé, KnownTypeAttribute se usa solo en deserialización, y si hay herencia, ¿no es así? Pero aquí solo está la serialización. Y sin el miembro de DataContract funciona bien.

¿Alguna idea?

¡Descubrí algo que funciona! Hay una clase para padres con una lista KnownTypes, que llené con todas las clases secundarias y que se usará en la serialización:

[DataContract] [KnownType( "GetKnownTypes" )] // for serialization class ResultContract { private static List<Type> KnownTypes { get; set; } public static List<Type> GetKnownTypes() { return KnownTypes; } static ResultContract() { KnownTypes = new List<Type>(); try { foreach( Type type in Assembly.GetExecutingAssembly().GetTypes() ) { if( !type.IsAbstract && type.IsSubclassOf( typeof( ResultContract ) ) ) { KnownTypes.Add( type ); } } } catch( Exception ex ) { Console.WriteLine( "Fatal error!" ); } } } [DataContract] class TestContract : *ResultContract* { ... } ...


Agregue esta línea:

[KnownType(typeof(TestContract))]

Así que eso

[Serializable] [KnownType(typeof(TestContract))] public class DNCJsonDictionary<K, V> : ...

Este es un problema conocido. Es por eso que los genéricos no funcionan del todo con WCF.

Pero la razón es fácil, se supone que WCF crea WSDL y podrá publicar su contrato. Está bien usar Generics para definir su contrato, pero WSDL necesita apuntar a una clase concreta, por lo tanto, necesita KnownType .