2012-02-29 54 views
2

我正在构建一个使用WCF的全新系统。我将使用契约优先方法来构建基于面向服务概念的服务。我有一个服务操作,返回用户的银行帐户详细信息。该帐户可以是“FixedAccount”或“SavingsAccount”类型。我已经设计了如下服务。合同优先SOA:设计业务领域:WCF

[ServiceContract] 
interface IMyService 
{ 
[OperationContract] 
AccountSummary AccountsForUser(User user); 
} 


[DataContract] 
class AccountSummary 
{ 
[DataMember] 
public string AccountNumber {get;set;} 

[DataMember] 
public string AccountType {get;set;} 
} 

这很好。

现在,我需要开发此服务的业务领域。我可以想到两种选择(总是欢迎任何新方法)

1)方法1:拿出一个BankAccount基类。从它派生出来的专门类是“FixedAccount”和“SavingsAccount”。 BankAccount将有一个方法为Transfer(string toAccount)。这成为我们熟悉的&有效的OOAD。这涉及用于AccountSummary DTO和FixedAccount/SavingsAccount域类之间映射的映射器。

2)方法2:不使用映射器转换层。

问题

1)假设我使用的方法1.是否有任何文章/教程,说明如何根据在DTO的ACCOUNTTYPE值AccountSummary的DTO映射到FixedAccount/SavingsAccount域类(有条件的映射) ?

2)如何在方法2中完成任务?


阅读: -

  1. http://www.soapatterns.org/service_facade.php

  2. SOA architecture data access

  3. Designing services and operations in WCF

  4. WCF Data Contract and Reference Entity Data?

  5. When does logic belong in the Business Object/Entity, and when does it belong in a Service?

+1

什么是你使用ESB或如何您的SOA层实现? – 2012-03-01 01:54:34

+0

@JamesBlack SOA将使用WCF – Lijo 2012-03-01 04:34:15

+1

实现WCF用于Web服务,但仅仅因为站起来的Web服务不会使其成为SOA层。如果您在用户和web服务之间放置消息总线,现在我们有更多面向服务的东西。对于你的问题,我会有两种不同的服务,但让他们去一个共同的控制器。 – 2012-03-01 12:08:28

回答

2
对于

方法之一,考虑使用像AutoMapper一个工具,而不是手动地执行所述映射。可以为你节省很多痛苦。 AutoMapper

+1

AutoMapper现在位于Github上:https://github.com/AutoMapper/AutoMapper – dotnetguy 2015-02-13 10:33:06

3

首先 - 您需要了解您是否真的需要全面的SOA。

SOA基本上意味着每个操作都在经历将我们的系统从其他系统中分离出来的服务。在极少数情况下(如果应用程序变得非常庞大) - 系统的一部分来自另一部分。

您的应用程序会与任何其他应用程序“通话”吗?

如果不是,你只是建立庞大的网站,释放你的想法和削减SOA的bullcrap。否则,你将最终得到无用的抽象层。

这是您应用第二种方法的唯一方法,因为您无法将域模型完全解耦合,而无需将其映射到其他位置。


如果确实需要SOA - 我们必须封装,从外部世界隐藏我们的领域模型。这意味着 - 我们的模型必须有一些映射到DTO。

是否有任何文章/教程,说明如何AccountSummary的DTO映射到FixedAccount/SavingsAccount

映射本身并不复杂的想法。这里有一个简单的方法来映射对象:

class AccountSummary{ 
    public string InterestingThing {get; set;} 
    public string AnotherThing {get; set;} 
} 
class AccountSummaryMapper{ 
    public static Map(BankAccount a){ 
    return new AccountSummary{ 
     InterestingThing=a.SomethingSomething, 
     AnotherThing=a.Something.Else.ToString() 
     }; 
    } 
} 
var accountSummary= 
    AccountSummaryMapper.Map(myBankAccount); 

这可能看起来没有效果。对象到对象映射器如Automapper可以提供帮助。通过教程,它应该足以让你去。想法并不困难 - 您可以创建地图,在应用程序启动时告诉Mapper关于它们的信息,然后使用Mapper通过给定的配置来映射您的对象。


另外 - 考虑映射方向。 Good object oriented code通常意味着您要么提问或要告诉对象的东西。对象不应该知道其他对象责任的内部运作。

比喻 - 父母完成孩子的家庭作业是不好的,因为孩子不会学习任何东西,父母将承担不必要的工作。相反,父母应该强迫孩子独立工作。

将AccountSummary直接映射到BankAccount并重新设置其状态就像做功课一样。不应该需要这样的映射。相反 - 告诉BankAccount BankAccount.DoHomework(铅笔,副本,一些强词)。


开拓业务领域

你不发展的业务领域。您开发的领域模型只是业务领域的一个反映,用于解决特定问题。

+0

谢谢。只是一个问题。如果我不使用SOA,为什么我应该去WCF?我可以直接参考这些项目,不是吗? – Lijo 2012-03-02 05:52:56

+0

@Lijo真的。 WCF将是多余的。另外 - 如果你真的走SOA,WCF不是强制性的。有很好的选择,例如http://nservicebus.com/ – 2012-03-02 08:33:14

2

在您指出这一部分之前,您需要确定您的客户将从每个服务方法调用中获得什么。客户是否需要FixedAccount/SavingsAccount,还是真的需要AccountSummary?

如果方法(如您的示例中的方法)仅返回AccountSummary,那么执行此操作的一种简单方法是向BankAccount添加一个方法,该方法创建AccountSummary。然后,当你想返回的东西(不管它是什么类型的帐户,但假设你的两个账户从的BankAccount继承),你只是这样做:

return someAccount.ToSummary() 

有些人会告诉你,这是不是“纯”从你的BankAccount类现在知道你的AccountSummary的意义上来说,但我个人总是发现它更容易处理。如果你不喜欢这样的话,像AutoMapper这样的工具也可以很有效地做到这一点(正如在其他答案中提到的那样)。

如果您要返回某种派生类而不是实际类本身,则无法在某处(如果您使用AutoMapper或自己写一些东西)将它映射到某处。避免必须执行任何映射的唯一方法是返回BankAccount本身,并且不建议将其用于服务,因为类的内部更改会影响服务。现在很容易记住,但在另一个开发人员进行维护的三年中,也很容易忘记它。映射也只能在整个服务中发送你明确告诉它的东西,所以它也有助于避免泄漏数据的错误。

BankAccount.ToSummary()的内容是很简单

public AccountSummary ToSummary() 
{ 
    AccountSummary s = new AccountSummary(); 
    s.AccountNumber = AccountNumber(); 
    s.Balance = Balance() 
    return s; 
}