如何在WCF中将接口用作DataContract

时间:2013-04-05 19:08:27

标签: c# wcf interface datacontract operationcontract

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

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

然后,我正在使用接口声明操作合同,但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的Sample project on GitHub

2 个答案:

答案 0 :(得分:2)

我用合约创建了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/" )]

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

答案 1 :(得分:0)

根据ServiceKnownTypeAttributeMSDN documentation),我根据情况改变了预期的类型。主要想法在类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;
    }
}

您必须在ServiceKnownType知道ServiceContract课程的界面中加入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的最终代码Sample project on GitHub