WCF - 使用完全相同的数据合同的多个服务合同
Posted
技术标签:
【中文标题】WCF - 使用完全相同的数据合同的多个服务合同【英文标题】:WCF - multiple service contracts using pretty same data contracts 【发布时间】:2011-08-20 06:26:51 【问题描述】:我有一个新问题要问 WCF 专家。
所以,我有一个类User
,它与我用于数据库操作的数据库中的“用户”表示很接近。现在,我想要 2 个不同的服务合同,将此类用作数据合同,但每个服务合同都有自己的方式......我的意思是,
public class DBLayer
void InsertUsers(List<User> 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<User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside
[ServiceContract]
public interface IService2
List<User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside
因此,这个想法是每个服务将获得不同类型的用户,'User'
的子集。请记住,我想将'User'
原样用于数据库操作,我有什么选择来实现这一目标?我真的需要创建不同的数据合约还是有其他更智能的方法?
最好的办法是不仅给我解决方案,还给我解释一些最佳实践和替代方案。
提前谢谢你。
编辑1: 我在这里添加了一个虚拟 DBLayer 类以获得更好的概述,以及为什么我认为在这种情况下继承可能不好。
解决方案是使用另一个“UserForService1
”和“UserForService2
”作为数据合约,它们最终会从/映射到“User
”,但我想要一些其他的观点。
EDIT2:非常好的文章在这种情况下对我有帮助:http://bloggingabout.net/blogs/vagif/archive/2009/03/29/iextensibledataobject-is-not-only-for-backward-compatibility.aspx
【问题讨论】:
我不是 WCF 专家,所以通过评论建议:听起来你应该有两个派生自 User 的类;一个具有 PropertyVisibleOblyForService1 属性,另一个具有另一个属性。 感谢您的回复...所以,您建议将这些属性取出并放入新的派生类中。问题是我希望“用户”类保持不变。 是的,我想你理解我的建议。但由于我不是 WCF 专家,而且我不知道您的项目、要求等,我不知道是否可以做您想做的事情,让 User 类保持不变。如果您发布更多详细信息,我可能会有所帮助,或者有更多 WCF 经验的人会参与进来。无论哪种方式都祝您好运! 感谢您的参与,欢迎任何 cmets。我知道一种解决方案是创建 2 个不同的数据合同,然后将“用户”映射到适当的数据合同,但对于这种情况来说,这可能是另一种更好的做法。我真的不认为在我的情况下继承会很好。谢谢。 好的,所以每个人都提出了同样的建议。也许我对我的要求不够清楚。我不想从“用户”中取出属性并放入其他派生类中,因为这个“用户”(及其属性按原样用于数据库操作)。因此,“PropertyVisibleOnlyForService1”和“PropertyVisibleOnlyForService2”都是用户表中的列。 【参考方案1】:您可以为每个服务创建单独的 DTO,但您的情况实际上是 Decorator pattern 的理想选择:
[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 类似的代码,它只公开你关心的内容......
【讨论】:
这是我一直在寻找的答案。非常好的一个!干杯!【参考方案2】:如果它们旨在代表不同类型的用户,它们应该是不同的类。我同意 cmets 中的 phoog,您应该从共享的 User 类中派生出您想要的类型,并将特定的服务属性添加到派生类中。
您为什么不认为在这种情况下继承会很好?如果您提供更多详细信息,我们可以尝试修改建议以适合您的实际问题。
【讨论】:
【参考方案3】:正如评论中所建议的,您可以从基本用户派生两个类,然后使用Data Contract Known Types,您可以实现您想要的目标。有关更多示例,请参见以下链接。
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
【讨论】:
鉴于 'User' 将 'PropertyVisibleOnlyForService1' 和 'PropertyVisibleOnlyForService2' 用于 db 操作,因为它们是 db 表中的列......这意味着我无法从 'User 中取出这些属性' 将它们放入派生类,除非我以某种方式隐藏它们?也许我应该试一试。【参考方案4】:如果您不想使用继承,例如:
[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<Service1User> GetUsers(); // user with 'PropertyVisibleOnlyForService1' inside
[ServiceContract]
public interface IService2
List<Service2User> GetUsers(); // user with 'PropertyVisibleOnlyForService2' inside
那我不知道你会怎么做。你在那一点上打破了类型声明的原则。以正常的 .NET 方式考虑它;如果您在应用程序中定义“用户”,那么它在任何地方都是相同的类型。某些属性不能对某些其他类或方法隐藏。
WCF 也会把这个类型信息打包到生成的 WSDL 中,而且它只会定义一次 User 类型,所以它需要知道有哪些属性。
现在,如果您只关心构建的实际 SOAP 消息,而不关心 WSDL 或任何从 WSDL 生成的客户端会看到什么,那么从技术上讲,您可以让它不将该属性发送到当 SOAP 消息为空时,执行以下操作:
[DataMember(EmitDefaultValue=false)]
那么当该属性为空时,它不会被包含在序列化中。但是,如果客户端是从 WSDL 生成的,那将没有真正的区别,因为它的 User 类型仍然必须包含这两个属性。它只会改变序列化,而不是向客户端发送类似的东西:
<User>
<PropertyVisibleOnlyForService1 nil="true" />
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>
它会改为发送:
<User>
<PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>
【讨论】:
感谢您的观点以及如何使用“Emit”的东西。我认为有它的想法很好,也许我将来可以使用它。以上是关于WCF - 使用完全相同的数据合同的多个服务合同的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 WCF 的数据合同中使用 DataMember 装饰多个属性?
WCF IIS 托管服务由单个服务实现的多个服务合同 - 如何通过配置在端点之间共享 uri