【问题标题】:How To Use Interface as DataContract in WCF如何在 WCF 中将接口用作 DataContract
【发布时间】:2013-04-05 19:08:27
【问题描述】:

我需要使用标准 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

【问题讨论】:

  • 您没有显示Thing 的定义方式——它也有[DataContract] 吗? [BsonDocument] 呢?通常,您必须为 WCF 服务定义 单独、轻量级(DTO 样式)对象 - 不要从 MongoDB 基类之类的东西继承 - 您不需要也不想序列化所有这些状态通过您的 WCF 服务....
  • 另外:WCF 是一个基于 XML 的消息传递系统 - 所以你在 WCF 中传递的任何东西都必须在 XML 模式 (XSD) 中表示; XSD 不支持接口 - 您需要使用具体类(也不支持泛型...)

标签: c# wcf interface datacontract operationcontract


【解决方案1】:

我已经使用合同创建了 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 指定命名空间,以便它们在客户端和服务上都匹配。

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

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

【讨论】:

    【解决方案2】:

    基于ServiceKnownTypeAttribute (MSDN 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;
        }
    }
    

    您必须在具有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的最终代码Sample project on GitHub

    【讨论】:

      猜你喜欢
      • 2012-04-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      相关资源
      最近更新 更多