Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 自定义值类型的DataContractSerializer_C#_Wcf_Datacontractserializer - Fatal编程技术网

C# 自定义值类型的DataContractSerializer

C# 自定义值类型的DataContractSerializer,c#,wcf,datacontractserializer,C#,Wcf,Datacontractserializer,我有一个WCF服务,它公开了一个类型TestTypeOne,该类型当前有一个名为ProductId的字符串属性: 公共类TestTypeOne { [DataMember(Name=“ProductId”)] 公共字符串ProductId{get;set;}//注意,它现在是一个字符串 } 我想将此属性的类型从string更改为名为ProductId的自定义值类型,但不破坏WCF契约(这仅适用于服务器端,客户端仍应将ProductId视为字符串。) 公共类TestTypeOne { [Data

我有一个WCF服务,它公开了一个类型
TestTypeOne
,该类型当前有一个名为
ProductId
的字符串属性:

公共类TestTypeOne
{
[DataMember(Name=“ProductId”)]
公共字符串ProductId{get;set;}//注意,它现在是一个字符串
}
我想将此属性的类型从
string
更改为名为
ProductId
的自定义值类型,但不破坏WCF契约(这仅适用于服务器端,客户端仍应将
ProductId
视为字符串。)

公共类TestTypeOne
{
[DataMember(Name=“ProductId”)]
public ProductId ProductId{get;set;}
}
自定义类型如下所示(为简洁起见,删除了大多数代码):

public struct ProductId:IEquatable
{
只读字符串productId;
公共产品ID(字符串ProductId)
{
this.productId=productId
}
公共重写字符串ToString()=>productId??string.Empty;
}
使用以下测试代码:

var sb=new StringBuilder();
使用(var writer=newXMLTextWriter(newStringWriter(sb)))
{
var dto=新的TestTypeOne{
ProductId=新ProductId(“1234567890123”)
};
var serializer=新的DataContractSerializer(typeof(TestTypeOne));
serializer.WriteObject(writer,dto);
writer.Flush();
}
Console.WriteLine(sb.ToString());
序列化时的预期输出应为:


1234567890123
我已经尝试过实现
ISerializable
,但这似乎只让我控制
ProductId
xml标记的内容,而不是标记本身(因此我可以实现
1234113
之类的事情)


理想情况下,我想对
ProductId
类型本身做点什么,因为这种类型在许多地方和许多合同中都使用。

您是否也尝试过将DataContract/DataMember属性添加到此ProductId类中

i、 e:

[DataContract]
public struct ProductId:IEquatable
{
[数据成员]
只读字符串productId;
公共产品ID(字符串ProductId)
{
this.productId=productId
}
公共重写字符串ToString()=>productId??string.Empty;
}

此外,本例中不需要name属性(name=“ProductId”),因为变量名与覆盖它的变量名相同。

我认为最简单的方法是实现
IXmlSerializable

public struct ProductId : IXmlSerializable
{
    readonly string productId;

    public ProductId(string productId)
    {
        this.productId = productId;
    }

    public override string ToString() => productId ?? string.Empty;

    XmlSchema IXmlSerializable.GetSchema() {
        return null;
    }

    void IXmlSerializable.ReadXml(XmlReader reader) {
        this = new ProductId(reader.ReadString());
    }

    void IXmlSerializable.WriteXml(XmlWriter writer) {
        writer.WriteString(this.productId);
    }
}
要针对这种情况调整WCF xsd生成(强制生成
xs:string
)-可以使用数据契约代理生成xsd。例如,您可以使用这样的suggorate:

public class ProductIdSurrogate : IDataContractSurrogate {
    public Type GetDataContractType(Type type) {
        if (type == typeof(ProductId))
            return typeof(string);
        return type;
    }

    public object GetObjectToSerialize(object obj, Type targetType) {
        throw new NotImplementedException();
    }

    public object GetDeserializedObject(object obj, Type targetType) {
        throw new NotImplementedException();
    }

    public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType) {
        return null;
    }

    public object GetCustomDataToExport(Type clrType, Type dataContractType) {
        return null;
    }

    public void GetKnownCustomDataTypes(Collection<Type> customDataTypes) {
        throw new NotImplementedException();
    }

    public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) {
        throw new NotImplementedException();
    }

    public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit) {
        throw new NotImplementedException();
    }
}
您可以将这种方法用于序列化本身,但我发现它更复杂


您可以阅读有关代理和WCF的更多信息,最底层有一个示例,说明如何将代理用于WSDL生成端点(“将代理用于元数据导出”部分)。

是的,不幸的是,这在xml中产生了:
1234567890123
,与想要的
1234567890123
不同,您也需要反序列化此类型吗?@Evk是的,但仍然只在服务器端(因此客户端应该以字符串属性结束,只有服务器正在进行ProductId的转换),这非常接近-序列化和反序列化时的xml是正确的,现在我只需要弄清楚wcf合同(它现在将其标记为值类型,但仍然显式指定类型,而不是使用“xs:string”)@Pondidum我已经添加了一些与此相关的信息。这将涵盖我所追求的-我想我今天在某个时候已经研究了代理,但很明显,它忽略了底部有用的部分。感谢您的帮助:)@Pondidum-您还可以使用获取正确的模式。参见或。
public class ProductIdSurrogate : IDataContractSurrogate {
    public Type GetDataContractType(Type type) {
        if (type == typeof(ProductId))
            return typeof(string);
        return type;
    }

    public object GetObjectToSerialize(object obj, Type targetType) {
        throw new NotImplementedException();
    }

    public object GetDeserializedObject(object obj, Type targetType) {
        throw new NotImplementedException();
    }

    public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType) {
        return null;
    }

    public object GetCustomDataToExport(Type clrType, Type dataContractType) {
        return null;
    }

    public void GetKnownCustomDataTypes(Collection<Type> customDataTypes) {
        throw new NotImplementedException();
    }

    public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData) {
        throw new NotImplementedException();
    }

    public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit) {
        throw new NotImplementedException();
    }
}
var exporter = new XsdDataContractExporter();
exporter.Options = new ExportOptions();
exporter.Options.DataContractSurrogate = new ProductIdSurrogate();
exporter.Export(typeof(TestTypeOne));