如何在WCF中使用接口作为数据契约

本文关键字:接口 数据 契约 WCF | 更新日期: 2023-09-27 18:07:56

我需要使用标准wsdl调用web服务操作,但客户端和服务器中的数据对象必须不同。

为公共库中的数据对象使用接口,在客户端和服务器中为其创建代理类。

然后,我使用接口声明操作契约,但是WCF不识别它。

我已经尝试使用DataContractSerializerBehavior和设置knownTypes,没有成功。

有人能帮帮我吗?我附上了一份完整的解决方案和更多的细节。

public interface Thing
{
   Guid Id {get;set;}
   String name {get;set;}
   Thing anotherThing {get;set;}
}
[DataContract]
public class ThingAtServer: BsonDocument, Thing // MongoDB persistence
{ 
   [DataMember]
   Guid Id {get;set;}
   //... 
}
[DataContract]
public class ThingAtClient: Thing, INotifyPropertyChanged // WPF bindings
{ 
   [DataMember]
   Guid Id {get;set;}
   //... 
}
[ServiceContract]
public interface MyService
{
  [OperationContract]
  Thing doSomething(Thing input);
}

点击这里查看TestCases在GitHub上的样例项目

如何在WCF中使用接口作为数据契约

我已经创建了WCF服务与合同:

[OperationContract]
CompositeTypeServer GetDataUsingDataContract( CompositeTypeServer composite );

我的CompositeTypeServer是这样的:

[DataContract( Namespace = "http://enes.com/" )]
public class CompositeTypeServer
{
    [DataMember]
    public bool BoolValue { get; set; }
    [DataMember]
    public string StringValue { get; set; }
}

然后我创建了类型为CompositeTypeClient的客户端项目:

[DataContract( Namespace = "http://enes.com/" )]
public class CompositeTypeClient
{
    [DataMember]
    public bool BoolValue { get; set; }
    [DataMember]
    public string StringValue { get; set; }
}

然后我将引用添加到我的服务并选择重用类型。一切都很顺利。我可以在客户端使用CompositeTypeClient

因此,技巧是为DataContract指定Namespace,以便它们在客户端和服务端都匹配。

[DataContract( Namespace = "http://enes.com/" )]

p。我可以根据要求提供完整的工作VS解决方案。

基于ServiceKnownTypeAttribute (MSDN文档),我根据情况更改了预期的类型。主要思想在XHelper类中实现,负责根据情况返回正确的Type[]:

public static class XHelper
{
    public static Boolean? IsClient = null;
    public static Type[] ClientTypes;
    public static Type[] ServerTypes;
    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider pProvider)
    {
        if (!IsClient.HasValue)
            throw new Exception("Invalid value");
        if (IsClient.Value)
            return ClientTypes;
        return ServerTypes;
    }
}

您必须在具有ServiceContract的接口中包含ServiceKnownType标记才能知道XHelper类。

[ServiceContract(Namespace = MyProxyProvider.MyNamespace)]
[ServiceKnownType("GetKnownTypes", typeof(XHelper))]
public interface MyService
{
    [OperationContract]
    Thing2 CopyThing(Thing1 input);
}

在测试单元开始时,它被告知每种情况下正确的Type[]:

    [AssemblyInitialize]
    public static void TestInitialize(TestContext pContext)
    {
        XHelper.ClientTypes = new Type[] { typeof(Thing1ProxyAtClient), typeof(Thing2ProxyAtClient), typeof(Thing2ProxyAtClient) };
        XHelper.ServerTypes = new Type[] { typeof(Thing1ProxyAtServer), typeof(Thing2ProxyAtServer), typeof(ThingNProxyAtServer) };
    }

点击这里查看TestCases在GitHub上的最终代码示例项目