简体   繁体   English

支持使用面向服务的体系结构传输富对象的设计模式?

[英]Design Pattern to Support the Transfer of a Rich Object using a Service-Oriented Architecture?

I have an Employee class that lives on the server and I wish to expose it in a web-service so that it can be consumed by a client. 我有一个存在于服务器上的Employee类,我希望在Web服务中公开它,以便客户端可以使用它。

Here is my class: 这是我的班级:

public class Employee
{
    public CountryCode { get; private set;} 
    public EmployeeType {get; set;}

    public bool IsTaxable
    {
       get
       {
           return (CountryCode != Codes.CaymanIslands 
                  && Status != EmployeeType.Contract);
       }
    }

    public void Employee(EmployeeType type, CountryCode code)
    {
        EmployeeType = type;
        CountryCode = code;
    } 

    private void Employee() {}
}

The private constructor and private setters help this class to be strongly typed, adhere to the DRY principle and also ensure it can only be instantiated in a valid state. 私有构造函数和私有setter帮助此类强类型化,遵循DRY原则并确保它只能有效状态下实例化。

For example, I ensure that IsTaxable is not set in the constructor but is dynamically evaluated based on the other class properties. 例如,我确保在构造函数中没有设置IsTaxable ,而是根据其他类属性动态评估。 In this way, if EmployeeType is modified the result of IsTaxable will reflect this change. 这样,如果修改了EmployeeType ,则IsTaxable的结果将反映此更改。 I use this simple example to highlight the fact that this object is rich in logic. 我使用这个简单的例子来强调这个对象具有丰富的逻辑。

Let's say that this Employee class lives on the server and I wish to gain access to it on the client. 假设这个Employee类存在于服务器上,我希望在客户端上访问它。 I build up a WebService (in .NET I'll use WCF), expose the class and using the out-of-the box tools connect and am able to use this class across the wire in my client. 我构建了一个WebService(在.NET中我将使用WCF),公开该类并使用开箱即用的工具连接,并且能够在我的客户端中使用此类。

The problem is that, doing so, will result in me losing most of this encapsulated logic . 问题在于,这样做会导致我失去大部分封装逻辑 At the receiving end, the client cannot see this rich class with it's private setters, it's hidden constructor, the logic in the IsTaxable property, etc. Instead, at client-side I will see a lightweight class like this: 在接收端,客户端无法使用它的私有setter,隐藏的构造函数,IsTaxable属性中的逻辑等来查看这个丰富的类。相反,在客户端我会看到一个像这样的轻量级类:

public class Employee
{
    public CountryCode { get; private set;} 
    public EmployeeType {get; }
    public bool IsTaxable {get; }
}

It is now possible for the client to instantiate the class in an invalid state by doing something like this: 现在,客户端可以通过执行以下操作来实例化处于无效状态的类:

Employee e = new Employee();
e.EmployeeType = EmployeeType.Contractor;
e.IsTaxable = true;

Is the loss of the rich object just a fact of service-oriented life and something that we have to live with? 失去富裕对象只是服务导向生活的一个事实,而我们必须要忍受这样的事情吗?

Are such service transferred objects to be seen as weak data transfer entities solely for the purpose of transmitting information and should be read-only. 此类服务转移对象是否仅仅是为了传输信息而被视为弱数据传输实体,并且应该是只读的。

At the client side should you (if required) wrap these in richer objects? 在客户端,您是否应该(如果需要)将它们包装在更丰富的对象中?

Is there any method of passing logic-intact rich objects across a wire or is there really a need to? 有没有任何方法可以通过线路传递逻辑完整的富对象,还是真的需要?

Are there any established patterns for dealing with such scenario? 是否有任何已建立的模式来处理这种情况?

Before looking at design patterns, the first thing you need to look into is where you actually want the logic to take place, and what actually happens if a 'rogue' client changes the data it is receiving over the wire. 在查看设计模式之前,您需要首先考虑的是您实际需要进行逻辑的位置,以及当“流氓”客户端更改通过网络接收的数据时实际发生的情况。

The way most client-server architectures are designed is that whatever the client tries to do has to be validated by the server. 大多数客户端 - 服务器体系结构的设计方式是,无论客户端尝试做什么,都必须由服务器进行验证。 So if the client decides to change IsTaxable to true, or change the Employee's name or ID etc., its won't have any effect on the real data that is stored on the server side. 因此,如果客户端决定将IsTaxable更改为true,或更改Employee的名称或ID等,则它将不会对存储在服务器端的实际数据产生任何影响。 The client has to perform an operation to update the data on the server and only if he has the right to do so will that data be propagated to the database and the rest of the system. 客户端必须执行操作以更新服务器上的数据,并且只有在他有权这样做时才将数据传播到数据库和系统的其余部分。

The client is always 'at risk' (it can be manipulated by the user, hacked by hackers, sniffed over the wire etc.) so the server must be secure enough to withstand such situations. 客户端始终处于“风险”状态(可由用户操纵,黑客入侵,嗅探电线等),因此服务器必须足够安全以抵御这种情况。

'Transfer Objects' are normally just intended to carry data. “传输对象”通常仅用于传输数据。 Any logic is then either performed by the client (for example formatting data to a more user-friendly presentation), or by the server. 然后,任何逻辑由客户端执行(例如,将数据格式化为更加用户友好的表示),或者由服务器执行。 If the clients needs to perform operations on the data then it needs to ask the server to do it (so that it is updated centrally). 如果客户端需要对数据执行操作,则需要请求服务器执行此操作(以便集中更新)。

So in your case, your webservice needs to expose operations for your clients to perform any logic you might need. 因此,在您的情况下,您的Web服务需要公开客户端的操作,以执行您可能需要的任何逻辑。

One other thing you might want to look at is how to create Contract First web services. 您可能想要了解的另一件事是如何创建Contract First Web服务。 This is considered a best practice, because it not only ensures your web services are interoperable with other platforms (eg Java), but also makes you think in terms of what operations and data you want to expose to your clients, and helps you avoid making mistakes (like expecting instances of objects which only the server has access to). 这被认为是最佳实践,因为它不仅可以确保您的Web服务可以与其他平台(例如Java)互操作,还可以让您考虑要向客户公开的操作和数据,并帮助您避免制作错误(例如期望只有服务器有权访问的对象的实例)。

Contract First means that you create your WSDL describing your operations and XSD describing the messages and objects to be transferred in XML. 契约优先意味着您创建描述操作的WSDL和描述要以XML传输的消息和对象的XSD。 They you just generate your code automatically from those WSDL and XSD documents. 他们只是从那些WSDL和XSD文档自动生成代码。

You can't do this for an arbitrary client, but if you control both client and server, you can add a reference to the assembly containing your Employee class to the client, then reuse this type for the WCF contract. 您不能为任意客户端执行此操作,但如果您同时控制客户端和服务器,则可以向客户端添加对包含Employee类的程序集的引用,然后将此类型重用于WCF合同。

In Visual Studio, you can do this with "Add Service Reference" / "Advanced" / "Reuse types in referenced assemblies". 在Visual Studio中,可以使用“添加服务引用”/“高级”/“在引用的程序集中重用类型”来执行此操作。

Is the loss of the rich object just a fact of service-oriented life and something that we have to live with? 失去富裕对象只是服务导向生活的一个事实,而我们必须要忍受这样的事情吗?

Yes, this is true. 是的,这是真的。 In a true service-oriented architecture, you don't share behavior between client and server, only exchange messages. 在真正面向服务的体系结构中,您不共享客户端和服务器之间的行为,只交换消息。 But if you're using WCF in a client-server architecture where you control both sides, you can use the above approach. 但是,如果您在控制双方的客户端 - 服务器体系结构中使用WCF,则可以使用上述方法。

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

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