2010-11-16 75 views
3

我用Google搜索,现在读了几个小时,我无法找到任何与我的具体方案涉及...使用接口采用WCF

我想在我的WCF服务合同使用接口松耦合的从导线的每端使用的类。这将使我们能够拥有一个低级别的程序集,其中只包含我们可以交给顾问的服务和数据合同(只是接口)。在线路的末端,他们可以实例化他们的数据类,这些数据类实现了我们的数据合约接口,通过线路将它发送给我们,然后我们的WCF服务会将输入数据转换/转换成版本的版本的数据类实现相同的接口。

下面是一个例子。 IDataContract包含我想通过电线传输的裸露信息。端点和其他WCF特定的配置都是默认的东西(我的问题可能在于此,所以我可以包含更多的东西,如果这是我需要改变的地方)。

编辑:我已经包含了更多的代码并重命名了几个类,以帮助它减少混淆。名称& DataContractAttributes的名称空间添加以及配置文件中的两个部分是基于this blog post的信息的新增加部分。如果我切换到抽象基类而不是接口,它可以工作。不过,如果可能的话,我想尽可能使用接口。

共享库(我的代码,使用客户端的作者共享):

public interface IDataContract 
{ 
    string MyProperty { get; set; } 
} 
[ServiceContract] 
public interface ITestService 
{ 
    [OperationContract] 
    IDataContract TestSharedInterface(IDataContract clientData); 
} 

客户端代码(他们的):

[DataContract(Name = "IDataContract", Namespace = "http://services.sliderhouserules.com")] 
public class ClientDataClass : IDataContract 
{ 
    [DataMember] 
    public string MyProperty { get; set; } 
} 
private static void CallTestSharedInterface() 
{ 
    EndpointAddress address = new EndpointAddress("http://localhost/ServiceContractsTest.WcfService/TestService.svc"); 
    ChannelFactory<ITestService> factory = new ChannelFactory<ITestService>("ITestService", address); 
    ITestService proxy = factory.CreateChannel(); 
    ((IClientChannel)proxy).Open(); 

    IDataContract clientData = new ClientDataClass() { MyProperty = "client data" }; 
    IDataContract serverData = proxy.TestSharedInterface(clientData); 
    MessageBox.Show(serverData.MyProperty); 
} 

客户端配置:

<system.runtime.serialization> 
    <dataContractSerializer> 
     <declaredTypes> 
      <add type="ServiceContractsTest.Contracts.DataContracts.IDataContract, ServiceContractsTest.Contracts"> 
       <knownType type="ServiceContractsTest.WcfClient.ClientDataClass, ServiceContractsTest.WcfClient"/> 
      </add> 
     </declaredTypes> 
    </dataContractSerializer> 
</system.runtime.serialization> 

服务器代码(我的):

public class TestService : ITestService 
{ 
    public IDataContract TestSharedInterface(IDataContract clientData) 
    { 
     ServerDataClass convertedClientData = (ServerDataClass)clientData; 
     IDataContract serverData = new ServerDataClass() { MyProperty = convertedClientData.MyProperty + " + server data added" }; 
     return serverData; 
    } 
} 
[DataContract(Name = "IDataContract", Namespace = "http://services.sliderhouserules.com")] 
public class ServerDataClass : IDataContract 
{ 
    [DataMember] 
    public string MyProperty { get; set; } 
} 

服务器配置:

<system.runtime.serialization> 
    <dataContractSerializer> 
     <declaredTypes> 
      <add type="ServiceContractsTest.Contracts.DataContracts.IDataContract, ServiceContractsTest.Contracts"> 
       <knownType type="ServiceContractsTest.WcfService.ServerDataClass, ServiceContractsTest.WcfService"/> 
      </add> 
     </declaredTypes> 
    </dataContractSerializer> 
</system.runtime.serialization> 

我收到的客户呼叫抱怨已知类型的序列化错误。我是否在该客户端类中缺少一些元数据标记?我甚至都不知道问题在哪里,因为我已经尝试了所有我能想到的搜索,似乎没有人处理过这种特定情况。

基本上,我想ClientDataClass序列化到<IDataContract><MyProperty>client data</MyProperty></IDataContract>然后能够反序列化到一个ServerDataClass实例。这似乎应该是可能的。

+0

我要指出,我读过很多关于ServiceKnownTypeAttribute和这里不符合该法案。我需要带有服务接口的程序集来完全不了解实现接口的类。我不知道我的问题是否清楚。 – sliderhouserules 2010-11-16 07:46:21

+0

你为什么要为同一份合同申请不同的名字?合同是合同... – 2010-11-16 07:55:30

+0

名称不是重要的部分,两个不同的具体实现是关键。来回传递的数据只是一个财产包。为什么它不能在电线的一端是Class1,如果它们都实现相同的接口,那么它们就会变成电线另一端的Class2? – sliderhouserules 2010-11-16 08:23:01

回答

3

如果您的数据合同接口WCF不知道实例化什么对象传入请求。在所有Add Service Reference读取WSDL并基于WSDL中的类型信息生成新类之后,不需要该类与服务中的类相同。

+0

如何告诉WCF *没有定义具有特定类名称的服务接口来专门实例化哪些类? App.config很好,我的实际.svc文件中的属性......无论如何。只要定义了服务接口的程序集就不必这样做。 – sliderhouserules 2010-11-16 08:24:33

+0

我应该提到你的回复至少帮助我获得了抽象基类的工作。我查看了添加服务引用生成的内容,并使用了其中的一些内容。那谢谢啦。 – sliderhouserules 2010-11-16 21:01:41

0

您可以创建一个BaseContract您ClientContract和ServerContract可以提供(财产),并且可以在各自的构造函数创建ClientContract或ServerContract的新实例时使用。 然后,您只需将BaseContract添加到您的共享库。

2

这个博客给了我正确的方向来找到我的问题的解决方案。其实我有完全相同的场景,如 sliderhouserules在他的帖子中描述。

但在我的情况下,我不能使用任何抽象或基类继承。所以我使用了TypesHelper类来自己读取dataContractSerializer部分,并将相关类型传递给WCF服务。

namespace ExampleNamespace 
{ 
    public interface IJustAInstance { } 

    [ServiceContract] 
    [ServiceKnownType("GetKnownTypes", typeof(ExampleNamespace.TypesHelper))] 
    public interface ICreateInstance 
    { 
    IJustAInstance CreateInstance(); 
    } 

    public static class TypesHelper 
    { 
    public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider) 
    { 
     DataContractSerializerSection section = (DataContractSerializerSection) 
     ConfigurationManager.GetSection(
     "system.runtime.serialization/dataContractSerializer"); 
     if (dataContractSerializerSection != null) 
     { 
     foreach (DeclaredTypeElement item in dataContractSerializerSection.DeclaredTypes) 
     { 
      foreach (TypeElement innterItem in item.KnownTypes) 
      { 
      Type type = Type.GetType(innterItem.Type); 
      if (typeof(IJustAInstance).IsAssignableFrom(type)) 
       yield return type; 
      } 
     } 
     } 
    } 
    } 
}