本文介绍了(不是预期的数据合同名称)DataContract序列化异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下代码:

  [DataContract] 
类TestContract {
私人字符串_Name ;
私人的Int32 _Age;

[数据成员(名称=名称)]
公共字符串名称{
{返回_Name; }
集合{_Name =价值; }
}

[数据成员(NAME =时代)]
公众的Int32年龄{
{返回_Age; }
集合{_Age =价值; }
}
}

[Serializable接口]
公共类DNCJsonDictionary< K,V> :ISerializable的{
&字典LT; K,V>字典=新词典< K,V>();

公共DNCJsonDictionary(){}

保护DNCJsonDictionary(的SerializationInfo信息,的StreamingContext上下文){
}

公共无效GetObjectData使用(的SerializationInfo信息,的StreamingContext上下文){
的foreach(在dict.Keys K键){
info.AddValue(key.ToString(),字典[关键]);
}
}

公共无效添加(K键,V值){
dict.Add(键,值);
}

公共V,则该[K指数] {
集合{字典[指数] =值; }
{返回的dict [指数] }
}
}

公共类MainClass {
公共静态字符串序列化(Object数据){
无功序列化=新DataContractJsonSerializer(data.GetType( ));
变种MS =新的MemoryStream();
serializer.WriteObject(MS,数据);

返回Encoding.UTF8.GetString(ms.ToArray());
}

公共静态无效的主要(){
DNCJsonDictionary<弦乐,对象>地址=新DNCJsonDictionary<弦乐,对象>();
地址[街] =30洛克菲勒广场;
地址[市] =纽约城;
地址[国家] =NY;

TestContract测试=新TestContract();
test.Name =CsDJ;
test.Age = 28;

DNCJsonDictionary<弦乐,对象>结果=新DNCJsonDictionary<弦乐,对象>();
结果[富] =酒吧;
结果[名称] =张三;
结果[时代] = 32;

结果[地址] =地址;

// ** ---这会抛出异常! --- **
结果[测试] =测试;

Console.WriteLine(序列化(结果));

到Console.ReadLine();
}
}

当我跑,我得到这个异​​常:



*类型Json_Dictionary_Test.TestContract'数据合同名称'TestContract://schemas.datacontract.org/2004/07/Json_Dictionary_Test:HTTP'预计不会。添加不是静态已知的已知类型的列表中的任何类型 - 例如,通过使用KnownTypeAttribute属性或通过将其添加到已知类型传递给DataContractSerializer列表*



但我不明白!据我所知,KnownTypeAttribute使用刚刚在反序列化,如果有继承,不是吗?不过这里只是序列化。并没有datacontract成员工作正常。
你知道吗?






我想通了一些作品!有一个KnownTypes名单,我充满了所有的子类和将在序列中使用的父类:

  [ DataContract] 
[KnownType(GetKnownTypes)] //进行序列化
类ResultContract {
私人静态列表<类型> KnownTypes {搞定;组; }

公共静态列表<类型> GetKnownTypes(){
返回KnownTypes;
}

静态ResultContract(){
KnownTypes =新的List<类型和GT;();
尝试{
的foreach {
如果(在Assembly.GetExecutingAssembly类型类型()GetTypes()。)(type.IsAbstract&安培;!&安培; type.IsSubclassOf(typeof运算(ResultContract))) {
KnownTypes.Add(类型);
}
}
}赶上(例外前){
Console.WriteLine(致命错误!);
}
}
}

[DataContract]
类TestContract:* ResultContract * {
...
$} b $ b ...


解决方案

添加此行:

  [KnownType(typeof运算(TestContract))] 

这样

  [Serializable接口] 
[KnownType(typeof运算(TestContract ))]
公共类DNCJsonDictionary< K,V> :...

这是一个已知的问题。这就是为什么仿制药确实与WCF不是那么回事。



不过,道理很容易, WCF是应该创建WSDL 并能够发布您的合同。这是一切都很好使用泛型来定义你的合同,但WSDL需要指向一些具体的类,因此你需要 KnownType


I have the following code:

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

When I run, I get this exception:

*Type 'Json_Dictionary_Test.TestContract' with data contract name 'TestContract:http://schemas.datacontract.org/2004/07/Json_Dictionary_Test' 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.*

But I don't understand that! As I know, KnownTypeAttribute is used just in deserialization, and if there is inheritance, isn't it? But here is just serialization. And without the datacontract member works fine.Any idea?


I figured out something that works! There is a parent class with a KnownTypes list, which I fill with all child classes and that will be used in serialization:

[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* {
    ...
}
...
解决方案

Add this line:

 [KnownType(typeof(TestContract))]

So that

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

This is a known issue. That is why generics does not quite work with WCF.

But the reason is easy, WCF is supposed to create WSDL and be able to publish your contract. It is all well and good to use Generics to define your contract but WSDL needs to point to some concrete class hence you need KnownType.

这篇关于(不是预期的数据合同名称)DataContract序列化异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-27 01:22