自定义类包含另一个自定义类时,DataContractResolver/KnownType问题

JCo*_*ine 5 .net c# fluent-nhibernate datacontractserializer known-types

我正在尝试使用DataContractJsonSerializer类将对象列表输出为json格式,但是我一直遇到以下错误.

Type 'Castle.Proxies.JokeCategoryProxy' with data contract name 
'JokeCategoryProxy:http://schemas.datacontract.org/2004/07/Castle.Proxies' 
is not expected. Consider using a DataContractResolver or 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.
Run Code Online (Sandbox Code Playgroud)

我知道这已经得到了回答,但只有在我的对象中有一个属性是另一个自定义对象时才会发生.

[DataContract]
[KnownType(typeof(ModelBase<int>))]
public class Joke : ModelBase<int>
{
    [DataMember]
    public virtual string JokeText { get; set; }

    [DataMember]
    public virtual JokeCategory JokeCategory { get; set; }
}

[DataContract]
[KnownType(typeof(ModelBase<int>))]
public class JokeCategory : ModelBase<int>
{
    [DataMember]
    public virtual string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

正如你可以看到Joke模型包含一个Joke Category对象,如果我删除了Joke Category并且只是有一个int(JokeCategoryId),那么错误就会消失,虽然是一个解决方案,但不是理想的解决方案,因为我希望没有类别再次查询.

下面是我用来生成json的代码

    public static ContentResult JsonResponse<TReturnType>(this Controller controller, TReturnType data)
    {
        using (var oStream = new System.IO.MemoryStream())
        {
            new DataContractJsonSerializer(typeof(TReturnType)).WriteObject(oStream, data);

            return new ContentResult
            {
                ContentType = "application/json",
                Content = Encoding.UTF8.GetString(oStream.ToArray()),
                ContentEncoding = Encoding.UTF8
            };
        }
    }
Run Code Online (Sandbox Code Playgroud)

让我最困惑的是错误引用了Castle.Proxies.JokeCategoryProxy(这是从哪里来的?!)

有什么建议?

J. *_* Ed 6

nHibernate假定除非另有说明,否则所有属性都是延迟加载的.
这意味着,在您的情况下,JokeCategory每当您拉动Joke物体时,都不会从数据库中拉出; 相反,动态生成"代理".
第一次访问该属性时,nHibernate知道从数据库中取出它.(这是nHib的懒加载方式)

所以基本上这里发生的是你希望你JokeCategory的类型JokeCategory,但因为它没有真正初始化 - 它是类型Proxy....

(这只是一个简短的解释;谷歌更多关于nHib及其如何工作以了解更多.你也可以查看夏天的nhibernate以获得对这个ORM的精彩介绍)

而且,对于你的问题:你有几个选择:

  1. 将Category属性配置为非惰性,这将强制nHibernate使用正确的对象类型初始化它

  2. (在我看来,更为可取)不要序列化您的模型实体; 相反 - 构建某种DTO,它将保存您的表示层所需的任何信息.
    这样,您的演示文稿不会受到域模型更改的影响,反之亦然.
    此外,您可以在DTO中保存所有必要信息,即使它与多个模型实体相关.

例如:

  public class JokeDTO
    {
       public int JokeId;
       /*more Joke properties*/
       public int JokeCategoryId;
       public string JokeCategoryName;
       /*etc, etc..*/
    }
Run Code Online (Sandbox Code Playgroud)