简体   繁体   English

如何以最优雅的方式处理具有不同属性的付款类型

[英]How to handle payment types with varying properties in the most elegant way

I'm using ASP.NET MVC 2. 我正在使用ASP.NET MVC 2。

My current payment types with properties

Keeping it simple, I have three payment types: credit card, e-check, or "bill me later". 为简单起见,我提供三种付款方式:信用卡,电子支票或“以后再付款”。 I want to: 我想要:

  1. choose one payment type 选择一种付款方式
  2. display some fields for one payment type in my view 在我的视图中显示一种付款方式的一些字段
  3. run some logic using those fields (specific to the type) 使用这些字段(特定于类型)运行一些逻辑
  4. display a confirmation view 显示确认视图
  5. run some more logic using those fields (specific to the type) 使用这些字段(特定于类型)运行更多逻辑
  6. display a receipt view 显示收据视图

Each payment type has fields specific to the type... maybe 2 fields, maybe more. 每个付款类型都有特定于该类型的字段...可能是2个字段,也许还有更多。 For now, I know how many and what fields, but more could be added. 现在,我知道有多少个字段,但可以添加更多字段。 I believe the best thing for my views is to have a partial view per payment type to handle the different fields and let the controller decide which partial to render (if you have a better option, I'm open). 我认为,对我而言,最好的办法是为每种付款方式提供部分视图以处理不同的字段,并让控制器确定要呈现的部分视图(如果您有更好的选择,我会开放)。 My real problem comes from the logic that happens in the controller between views. 我真正的问题来自视图之间控制器中发生的逻辑。 Each payment type has a variable number of fields. 每种付款类型都有可变数量的字段。 I'd like to keep everything strongly typed, but it feels like some sort of dictionary is the only option. 我想保留所有类型的强类型,但是感觉只有某种字典是唯一的选择。 Add to that specific logic that runs depending on the payment type. 添加到根据付款类型运行的特定逻辑。

In an effort to keep things strongly typed, I've created a class for each payment type. 为了保持强类型,我为每种付款类型创建了一个类。 No interface or inherited type since the fields are different per payment type. 没有界面或继承的类型,因为每个付款类型的字段都不同。 Then, I've got a Submit() method for each payment type. 然后,对于每种付款类型,我都有一个Submit()方法。 Then, while the controller is deciding which partial view to display, it also assigns the target of the submit action. 然后,在控制器决定显示哪个局部视图的同时,它还分配了提交动作的目标。

This is not elegant solution and feels very wrong. 这不是一个很好的解决方案,感觉很不对劲。 I'm reaching out for a hand. 我正在伸出援手。 How would you do this? 你会怎么做?

It's one for thing for, say, an Order object to not really care about the particular payment type--just knowing that there is a PledgedAmount and a DepositedAmount property, for example, is enough for that class to do its job (eg, "don't allow myself to go to Shipped status if order is not charged, via whatever payment method, I don't really care, as long as it's charged somehow I'm cool"). 例如,对于Order对象来说,它并不真正在乎特定的付款类型是PledgedAmount -仅知道例如存在一个PledgedAmountDepositedAmount属性就足以使该类完成其工作(例如,“如果通过任何付款方式都不收取订单费用,就不要让自己进入“已发货”状态,我并不介意,只要我以某种方式收取费用就可以了。”)

It's another thing for the UI to not really care: you either write a switch to load the right view and be done with it, or you end up creating a dictionary-like collection of fields, rules, and validation metadata and let the UI generate itself dynamically. UI并不是很在乎另一件事:您编写了一个switch来加载正确的视图并完成操作,或者最终创建了类似字典的字段,规则和验证元数据集合,并让UI生成本身是动态的。

For example, I took the latter approach when I was adding international address support for one of my applications. 例如,当我为我的一个应用程序添加国际地址支持时,我采用了后一种方法。 I abstracted addresses into a common set of fields: AdministrativeArea , Municipality , etc, and defined an AddressScheme class which defined AddressFieldRule s for each field, stating whether or not it was required, if a regex should be applied, if there is a specific set of allowed values, etc. It was appropriate since we could add or remove countries to the allowed list at any time without recompiling and redeploying the application; 我将地址抽象为一组通用字段: AdministrativeAreaMunicipality等,并定义了一个AddressScheme类,该类为每个字段定义了AddressFieldRule ,指出是否需要使用正则表达式,是否有特定的设置这是适当的,因为我们可以随时在允许列表中添加或删除国家/地区,而无需重新编译和重新部署应用程序; the UI could dynamically generate itself based on the AddressScheme , which itself was loaded from the database. UI可以根据AddressScheme动态生成自身,而AddressScheme本身是从数据库中加载的。 Sweet. 甜。

But are you really going to be adding payment types (a) with great frequency or (b) without re-compiling your application? 但是,您是否真的要在不重新编译您的应用程序的情况下增加付款类型(a)或增加付款类型(b)? Sometimes you really do need an actual Toaster instead of a Breakfast Cooking Machine w/ Bread and Other Yeast-Based Goods Browning Module, so just add a switch or a dictionary that maps a type to the correct view: I think it's perfectly acceptable for the UI to have to be able to distinguish among these types, and, more importantly, for you to custom-write and tailor the presentation of each type--but the higher-up parts might benefit from some abstraction. 有时您确实确实需要一台真正的烤面包机,而不是一台带面包和其他基于酵母的商品褐变模块的早餐烹饪机,因此只需添加一个将类型映射到正确视图的开关或字典即可:我认为对于UI必须能够区分这些类型,更重要的是,您可以自定义编写和定制每种类型的表示形式-但较高的部分可能会受益于某些抽象。 I talked about that in my answer to a different question related to billing. 我在回答与计费有关的另一个问题时谈到了这一点。

In your example, you can share common code for steps 1, 4, and 6, but delegate to specific UI methods and views for steps 2, 3, and 5. And the world will still spin round. 在您的示例中,您可以共享步骤1、4和6的通用代码,但可以委派给特定的UI方法和步骤2、3和5的视图。世界仍然会旋转。

My two cents. 我的两分钱。 Good luck! 祝好运!

It sounds like you have three distinct workflows, each pertaining to a different payment method chosen by the user. 听起来您有三个不同的工作流程,每个工作流程都与用户选择的不同付款方式有关。 While you only explicitly indicate steps 3 and 5 as having payment specific concerns, it would seem that everything after step 1 must display payment specific information (unless in step 4 the user isn't confirming payment specific information, and in step 6 their receipt doesn't indicate how they've paid). 尽管您仅将第3步和第5步明确表示为有特定付款问题,但似乎第1步之后的所有内容都必须显示特定付款信息(除非在第4步中,用户没有确认特定付款信息,而在第6步中,他们的收据没有不能说明他们的付款方式)。

In this case, you'll probably create a bigger mess for yourself trying to combine all of this into a single workflow rather than creating distinct controllers for each payment type, factoring out any common behavior for reuse by each of the three paths. 在这种情况下,您可能会尝试将所有这些合并到一个工作流中,而不是为每种付款类型创建不同的控制器,从而排除任何常见行为,以供这三个路径重用,从而为自己造成更大的混乱。

As an aside, while you indicated that you weren't using an interface, the reason you gave seems a little troubling. 顺便说一句,虽然您表示您没有使用接口,但给出的原因似乎有点令人不安。 It sounded like you might have used an interface if the payment types contained the same fields. 如果付款类型包含相同的字段,听起来您可能使用了界面。 Interfaces are for defining behavior contracts, so you shouldn't be using them to define common data. 接口用于定义行为契约,因此您不应该使用它们来定义公共数据。

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

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