我正在使用WCF构建一个全新的系统。我将使用契约优先方法来获得基于面向服务的概念构建的服务。我有一个服务操作,返回用户的银行帐户详细信息。该帐户可以是“FixedAccount”或“SavingsAccount”类型。我按如下方式设计了这项服务。
[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(字符串toAccount)。这成为我们熟悉的&有效的OOAD。这涉及到映射器,用于在AccountSummary DTO和FixedAccount / SavingsAccount域类之间进行映射。
2)方法2 :不使用映射器转换层。
问题
1)假设我正在使用方法1.是否有任何文章/教程解释如何根据DTO(条件映射)中的AccountType值将AccountSummary DTO映射到FixedAccount / SavingsAccount域类?
2)如何在方法2中完成任务?
READING: -
答案 0 :(得分: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(铅笔,字帖,一些强词)。
开发业务领域
您不开发业务领域。您开发的域模型只是业务领域的反映,用于解决特定问题。
答案 1 :(得分:2)
对于方法一,请考虑使用AutoMapper之类的工具,而不是手动实现映射。可以为你节省很多痛苦。 AutoMapper
答案 2 :(得分:2)
在您确定此部分之前,您需要确定您的客户将从每个服务方法调用获得什么。客户端是否需要FixedAccount / SavingsAccount,或者它真的需要AccountSummary吗?
如果方法(如示例中的方法)只返回AccountSummary,那么一种简单的方法是向BankAccount添加一个创建AccountSummary的方法。然后,当你想要返回一些东西时(无论它是什么类型的帐户,但假设你的两个帐户继承自BankAccount),你只需要这样做:
return someAccount.ToSummary()
有些人会告诉你,你的BankAccount课程现在知道你的AccountSummary,这并不是“纯粹的”,但我个人总是觉得它更容易使用。如果您不喜欢这样,AutoMapper等工具也可以非常有效地完成这项工作(如其他答案中所述)。
如果你要返回某种类型的派生类而不是实际的类本身,那么就无法将它映射到某个地方(如果你使用AutoMapper或自己写一些东西)。避免必须执行任何映射的唯一方法是返回BankAccount本身,并且不推荐用于服务,因为对类的内部更改可能会影响服务。现在很容易记住,但是当另一位开发人员进行维护时,3年内也很容易忘记它。映射也只发送您明确告诉它的服务内容,因此它有助于避免泄漏数据的错误。
BankAccount.ToSummary()的内容非常简单
public AccountSummary ToSummary()
{
AccountSummary s = new AccountSummary();
s.AccountNumber = AccountNumber();
s.Balance = Balance()
return s;
}