繁体   English   中英

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

[英]WCF - multiple service contracts using pretty same data contracts

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

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

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'作为数据库操作,我可以选择实现这一目标吗? 我真的需要创建不同的数据合同还是有另一种更聪明的方法?

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

先感谢您。

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

一个解决方案是将另一个' 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类派生您想要的类型,并将特定的服务属性添加到派生类。

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

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

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

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

[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消息中当它为null时,通过执行:

    [DataMember(EmitDefaultValue=false)]

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

<User>
  <PropertyVisibleOnlyForService1 nil="true" />
  <PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>

它会发送:

<User>
  <PropertyVisibleOnlyForService2>something</PropertyVisibleOnlyForService2>
</User>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM