You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

WCF抽象类继承对象返回时序列化错误求助

解决WCF抽象类子类序列化错误及URL疑问

首先来说你遇到的序列化错误——这是WCF里非常常见的问题,因为DataContractSerializer是静态类型感知的,它默认不知道你会返回License的哪个子类实例,必须明确告诉它哪些类型是“已知的”才能正常序列化。

一、修复序列化错误的核心方案

方法1:直接标注已知类型(适合子类数量固定的场景)

给你的抽象类License添加KnownTypeAttribute,把所有继承它的子类都列进去,让序列化器提前知晓这些类型:

[DataContract]
[KnownType(typeof(LicenseMay2018))]
[KnownType(typeof(LicenseApril2018))]
public abstract class License 
{ 
    [DataMember] 
    public int ManagedObjectCount { get; set; } 
}

这样修改后,DataContractSerializer在处理返回值时,就能识别并序列化LicenseMay2018LicenseApril2018的实例了。

方法2:动态获取已知类型(适合子类动态新增或数量较多的场景)

如果后续会频繁新增License子类,或者子类是动态加载的,可以用KnownType的动态方法形式,通过反射自动获取所有继承License的类型:

[DataContract]
[KnownType("GetKnownLicenseTypes")]
public abstract class License 
{ 
    [DataMember] 
    public int ManagedObjectCount { get; set; } 

    private static IEnumerable<Type> GetKnownLicenseTypes()
    {
        // 反射获取当前程序集中所有继承License的非抽象类
        return typeof(License).Assembly.GetTypes()
                             .Where(t => t.IsSubclassOf(typeof(License)) && !t.IsAbstract);
    }
}

这种方式不用每次加新子类都修改抽象类的属性,灵活性更高。

额外注意点

要确保BE端和FE端的License类及其子类命名空间完全一致,WCF是通过“命名空间+类型名”来识别数据契约的,命名空间不匹配也会导致序列化失败。

二、关于两个URL的来源解释

  1. http://tempuri.org/:这是WCF服务契约的默认命名空间。当你创建WCF服务时,如果没有在ServiceContractAttribute里显式指定命名空间,WCF就会自动使用这个默认值。你可以通过修改服务契约的属性自定义它,比如:[ServiceContract(Namespace = "http://yourcompany.com/services")]
  2. http://schemas.datacontract.org/2004/07/:这是DataContract的默认命名空间前缀,后面拼接的是你的类的实际命名空间(比如NMS.Frontend.DataTypes)。DataContractSerializer会自动把类的命名空间转换成这种URL格式,用来唯一标识数据契约。你也可以通过DataContractAttributeNamespace属性自定义,比如:[DataContract(Namespace = "http://yourcompany.com/license/types")]

错误信息回顾

你遇到的错误本质就是序列化器未识别到LicenseMay2018这个子类类型,按照上面的方法添加已知类型后,问题就能解决:

There was an error while trying to serialize parameter http://tempuri.org/:ActivateLicenseResult. The InnerException message was 'Type 'NMS.Frontend.DataTypes.LicenseMay2018' with data contract name 'LicenseMay2018:http://schemas.datacontract.org/2004/07/NMS.Frontend.DataTypes' is not expected. Consider using a DataContractResolver if you are using DataContractSerializer 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 the serializer.'. Please see InnerException for more details.

内容的提问来源于stack exchange,提问作者Azzurro94

火山引擎 最新活动