WCF – 使用相同数据协定的多个服务合同

我有一个关于WCF大师的新问题。

所以,我有一个类User ,它接近我用于数据库操作的DB的’User’表示。 现在,我想有两个不同的服务合同,使用这个类作为数据合同,但每个都以他们自己的方式……我的意思是,

 public class DBLayer { void InsertUsers(List userList) { // both 'PropertyVisibleForService1' and 'PropertyVisibleForService2' // are used HERE to be inserted into their columns } } [DataContract] public class User { [DataMember] public string PropertyVisibleOnlyForService1{...} [DataMember] public string PropertyVisibleOnlyForService2{...} } [ServiceContract] public interface IService1 { List GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside } [ServiceContract] public interface IService2 { List GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside } 

因此,我们的想法是每个服务都会获得一个不同类型的用户,即'User'子集。 请记住,我想使用'User'作为数据库操作,我可以选择实现这一目标吗? 我真的需要创建不同的数据合同还是有另一种更聪明的方法?

最好不仅要给我解决方案,还要向我解释一些最佳实践和替代方案。

先感谢您。

EDIT1:我在这里添加了一个虚拟DBLayer类,以便更好地概述,以及为什么我认为在这种情况下inheritance可能不太好。

一个解决方案是将另一个’ UserForService1 ‘和’ UserForService2 ‘作为数据契约,将最终映射到’ User ‘,但我想要其他一些观点。

EDIT2:在这种情况下帮助我的非常好的文章: http : //bloggingabout.net/blogs/vagif/archive/2009/03/29/iextensibledataobject-is-not-only-for-backward-compatibility.aspx

您可以为每个服务创建单独的DTO,但您的案例实际上是Decorator模式的理想选择:

 [DataContract] public class UserForService1 : User { private User mUser; public UserForService1(User u) { mUser = u; } //expose only properties you'd like the user of this data contract to see [DataMember] public string SomeProperty { get { //always call into the 'wrapped' object return mUser.SomeProperty; } set { mUser.SomeProperty = value; } } // etc... } 

而对于Service2类似的代码,只暴露你在那里关心的东西……

如果它们旨在表示不同类型的用户,则它们应该是不同的类。 我同意评论中的phoog,您应该从共享的User类派生您想要的类型,并将特定的服务属性添加到派生类。

在这种情况下,为什么你不认为inheritance会好? 如果您向我们提供更多详细信息,我们可以尝试修改建议以适合您的实际问题。

正如评论中所建议的那样,您可以从基本用户派生两个类,然后使用数据合同已知类型 ,您可以实现所需的目标。 有关更多示例,请参阅以下链接。

http://www.freddes.se/2010/05/19/wcf-knowntype-attribute-example/

http://footheory.com/blogs/bennie/archive/2007/07/28/handling-data-contract-object-hierarchies-in-wcf.aspx

如果您不想使用inheritance,请执行以下操作:

 [DataContract] public class User { } [DataContract] public class Service1User : User { [DataMember] public string PropertyVisibleOnlyForService1{...} } [DataContract] public class Service2User : User { [DataMember] public string PropertyVisibleOnlyForService2{...} } [ServiceContract] public interface IService1 { List GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside } [ServiceContract] public interface IService2 { List GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside } 

然后我不确定你会做什么。 那时你打破了类型声明的主体。 以正常的.NET方式来思考它; 如果您在应用程序中定义“用户”,那么它在任何地方都是相同的类型。 某些属性无法从某些其他类或方法中隐藏。

WCF也会将这种类型的信息打包到生成的WSDL中,它只会定义一次User类型,因此它需要知道那里有哪些属性。

现在,如果你关心的只是构造的实际SOAP消息,并且你不关心WSDL或者WSDL将生成的任何客户端将看到什么,那么从技术上讲,你可以让它不将该属性发送到SOAP消息中当它为null时,通过执行:

  [DataMember(EmitDefaultValue=false)] 

然后当该属性为null时,它不会包含在序列化中。 如果客户端是从WSDL生成的,那将没有什么区别,因为它的User类型仍然必须包含这两个属性。 它只会改变序列化,而不是像以下那样向客户端发送:

   something  

它会发送:

  something