【发布时间】:2011-04-11 05:55:50
【问题描述】:
更新:添加了一些示例代码以帮助澄清。
嗨,感觉这不应该那么复杂,但我想我只是不知道我正在尝试做的事情的正确名称。我正在处理一个 ASP.net 项目。
这个概念很简单: 我有一个提供一些 ecomm 功能的库。 库中的一个类包含有关计算税收的功能。 库中的一个类围绕购物车标题。 此类由 Web 项目使用。
会有一个类似的方法:carthead.SaveCart。 在 SaveCart 中,它需要调用 tax.CalculateTax
我需要做的是想办法让 carthead.SavCart 始终可以访问特定函数,例如 tax.CalculateTax(例如,该函数必须始终对库可用)。
但是,我想允许任何人创建不同版本的 tax.CalculateTax 方法。
我尝试使用可覆盖的基类做一些事情,但我发现即使在 Web 项目中覆盖税基类,它也只会在我调用时调用税类的覆盖版本网络项目。 我不能将税收类变成一个接口,因为当我这样做时,我不能将 tax.CalculateTax 的结果定义为一个列表(因为在这种情况下 t 是一个接口,而不是一个实际的类) - 这个列表必须由 carthead.SaveCart 方法使用。
因此,当您单步执行代码时,您会发现当 Web 项目调用 carthead.SaveCart 方法时,carthead.SaveCart 方法无法从 Web 项目中访问被覆盖的代码...并导致调用 tax.CalculateTax 方法的非覆盖版本。
我确定我遗漏了一些东西,但我什至不确定我应该研究什么,或者我想要完成的事情的正确名称是什么。
归根结底,我需要能够重写一个方法,并从库中的不可重写方法调用该方法的重写版本。
谁能告诉我我搞砸了什么或者我应该看什么?
更新: 添加了一些代码 sn-ps 以帮助澄清:
这是有问题的 CartHeader 类的一部分:
Public Class CartHeader
'其他类的东西省略了
Public Function UpdateCartStep2(ByVal CartNo As Long, ByVal Username As String, _
ByVal PmtMethod As String, ByVal ShipMethod As String, _
ByVal ShipComplete As Boolean, ByVal ShipCost As Double, _
ByVal ShipInstr As String, Optional ByVal TaxGroup As String = "", _
Optional ByVal PickupLoc As String = "", _
Optional ByVal FuelSurcharge As Double = 0, _
Optional ByVal Misc As String = "", _
Optional ByVal TaxThisSomeTaxOrder As Boolean = False, _
Optional ByVal ShipToID As Long = 0, _
Optional ByVal ShipToZip As String = "", _
Optional ByVal mCustCode As String = "", _
Optional ByVal CustTax As Tax = Nothing) As Integer
'=================>
'note that the last parameter is new which is what we're currently using to pass in the customtax class so that we can consume it inside this method
'==================>
If IsNothing(CustTax) Then
CustTax = New Tax
End If
'6-29-08 this stored proc was updated to allow for fuel surcharge
'added fuel surcharge parameter
Dim Resultval As Integer
Dim strConnect As New SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString)
Dim SqlCommand As New SqlCommand("sp_UpdateCartStep2", strConnect)
Try
Dim SubTotalAmt As Double
SubTotalAmt = GetCartSubTotal(CartNo)
GetCartHeader(CartNo)
Dim CartTax As Double
Dim SystemTypeID As Integer = CInt(ConfigurationManager.AppSettings("SystemTypeID").ToString)
Select Case SystemTypeID
Case 1
If profile.AllowTerms = False Then
CartTax = CalcTax(SubTotalAmt, ShipCost, FuelSurcharge, m_Ship_State_Province)
Else
CartTax = 0
End If
Case 2
'6-29-08 added to figure fuel surcharge
'Dim CustTax As New Tax
'Dim CustCode As String = System.Web.HttpContext.Current.Profile("CustCode")
Dim lCustTax As New List(Of Tax)
'=========================>
'note that this part of the header must always call into the calctax method.
'it should be able to call the custom method if it has been defined.
lCustTax = CustTax.wa_cc_CalcTax(mCustCode, ShipToID, SubTotalAmt, ShipCost, FuelSurcharge, CStr(m_Ship_State_Province), CStr(ShipToZip))
'==========================>
For Each ct As Tax In lCustTax
CartTax += ct.Tax
Next
'CartTax = CalcTax(SubTotalAmt, ShipCost, FuelSurcharge, m_Ship_State_Province, TaxGroup)
End Select
SqlCommand.CommandType = CommandType.StoredProcedure
strConnect.Open()
SqlCommand.Parameters.AddWithValue("@CartNo", SqlDbType.BigInt).Value = CartNo
SqlCommand.Parameters.AddWithValue("@Username", SqlDbType.VarChar).Value = Username
SqlCommand.Parameters.AddWithValue("@PmtMethod", SqlDbType.VarChar).Value = PmtMethod
SqlCommand.Parameters.AddWithValue("@ShipMethod", SqlDbType.VarChar).Value = ShipMethod
SqlCommand.Parameters.AddWithValue("@ShipCompleteFlag", SqlDbType.Bit).Value = ShipComplete
SqlCommand.Parameters.AddWithValue("@ShipCost", SqlDbType.Money).Value = ShipCost
SqlCommand.Parameters.AddWithValue("@Tax", SqlDbType.Money).Value = CartTax
SqlCommand.Parameters.AddWithValue("@ShipInstr", SqlDbType.VarChar).Value = ShipInstr
SqlCommand.Parameters.AddWithValue("@PickupLoc", SqlDbType.VarChar).Value = PickupLoc
SqlCommand.Parameters.AddWithValue("@FuelSurcharge", SqlDbType.Float).Value = FuelSurcharge
'1-30-08 Changed to accomodate holding the carrier number when selecting collect freight
'required modification of the sp_UpdateCartStep2 stored procedure.
SqlCommand.Parameters.AddWithValue("@Misc3", SqlDbType.VarChar).Value = Misc3
SqlCommand.ExecuteNonQuery()
Resultval = 0
Catch ex As Exception
Resultval = -1
System.Web.HttpContext.Current.Trace.Write(ex.Message)
Finally
strConnect.Close()
End Try
Return Resultval
End Function
结束类
这是我们用作基类的类...如果基函数 calcs 不适用,它会覆盖 wa_cc_calctax。
Public Class Tax
Private _Tax As Double
Public Property Tax() As Double
Get
Return _Tax
End Get
Set(ByVal value As Double)
_Tax = value
End Set
End Property
Private _TaxRate As Double
Public Property TaxRate() As Double
Get
Return _TaxRate
End Get
Set(ByVal value As Double)
_TaxRate = value
End Set
End Property
Private _TaxDesc As String
Public Property TaxDesc() As String
Get
Return _TaxDesc
End Get
Set(ByVal value As String)
_TaxDesc = value
End Set
End Property
Private _TaxGroupID As String
Public Property TaxGroupID() As String
Get
Return _TaxGroupID
End Get
Set(ByVal value As String)
_TaxGroupID = value
End Set
End Property
Private _TaxJurisdictionID As String
Public Property TaxJurisdictionID() As String
Get
Return _TaxJurisdictionID
End Get
Set(ByVal value As String)
_TaxJurisdictionID = value
End Set
End Property
Private _TaxCustCode As String
Public Property TaxCustCode() As String
Get
Return _TaxCustCode
End Get
Set(ByVal value As String)
_TaxCustCode = value
End Set
End Property
Private _TaxFreight As Boolean
Public Property taxFreight() As Boolean
Get
Return _TaxFreight
End Get
Set(ByVal value As Boolean)
_TaxFreight = value
End Set
End Property
Public Enum TaxableStatus
All
None
some
End Enum
''' <summary>
''' It will first try to figure out if we're shipping to the same zip as the ship to
''' if it is the same, then we'll use the ship-tos tax group
''' if it is different, then we'll go to manual tax.
''' in manual tax, the customer record is reviewed and the class_1id field is interogated.
''' The code selected tells us what states the customer is taxable for.
''' If we are in those states, then the customer tax group is chosed based on the state.
''' </summary>
''' <param name="mCustCode"></param>
''' <param name="mShipToID"></param>
''' <param name="SubTotalAmt"></param>
''' <param name="FreightCost"></param>
''' <param name="FuelSurcharge"></param>
''' <param name="m_Ship_State_Province"></param>
''' <param name="m_Zip"></param>
''' <param name="TaxGroup"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Overridable Function wa_cc_CalcTax(ByVal mCustCode As String, _
ByVal mShipToID As String, _
ByVal SubTotalAmt As Double, _
ByVal FreightCost As Double, _
ByVal FuelSurcharge As Double, _
ByVal m_Ship_State_Province As String, _
ByVal m_Zip As String, _
Optional ByVal TaxGroup As String = "") As List(Of Tax)
'do some 'normal' tax calcs.
Return New List(Of Tax)
End Function
结束类
这是覆盖 wa_cc_calctax 函数的 CustomTax 类:
Public Class CustomTax
Inherits Tax
''' <summary>
''' It will first try to figure out if we're shipping to the same zip as the ship to
''' if it is the same, then we'll use the ship-tos tax group
''' if it is different, then we'll go to manual tax.
''' in manual tax, the customer record is reviewed and the class_1id field is interogated.
''' The code selected tells us what states the customer is taxable for.
''' If we are in those states, then the customer tax group is chosed based on the state.
''' </summary>
''' <param name="mCustCode"></param>
''' <param name="mShipToID"></param>
''' <param name="SubTotalAmt"></param>
''' <param name="FreightCost"></param>
''' <param name="FuelSurcharge"></param>
''' <param name="m_Ship_State_Province"></param>
''' <param name="m_Zip"></param>
''' <param name="TaxGroup"></param>
''' <returns></returns>
''' <remarks></remarks>
Public Overrides Function wa_cc_CalcTax(ByVal mCustCode As String, _
ByVal mShipToID As String, _
ByVal SubTotalAmt As Double, _
ByVal FreightCost As Double, _
ByVal FuelSurcharge As Double, _
ByVal m_Ship_State_Province As String, _
ByVal m_Zip As String, _
Optional ByVal TaxGroup As String = "") As List(Of Tax)
Dim lTX As New List(Of Tax)
Dim mUseP21Tax As Boolean = True
If mShipToID <= 0 Then
mUseP21Tax = False
End If
If FreightCost <= 0 Then
FreightCost = 0
End If
Dim tx As New CustomTax
Dim ZipMatch As Boolean
If mShipToID > 0 Then
'we're dealing with a selected ship to so we should see if it all still matches
ZipMatch = CheckZipAgainstShipTo(m_Zip, mCustCode, mShipToID)
Else
'this item is not a selected ship-to so no need to look for a match
ZipMatch = False
End If
If ZipMatch = True Then
lTX = LookupTaxForShipTo(mCustCode, mShipToID, SubTotalAmt, FreightCost)
Else
lTX = LookupManualTax(mCustCode, m_Ship_State_Province, SubTotalAmt, FreightCost, , m_Zip)
End If
Return lTX
结束函数 结束类
所以问题的部分原因是: 1) 如果我将 Tax 类设为接口或抽象类,那么我必须将其“新建”为 cartheader 类中的新类,以便我可以调用 wa_cc_lookupclass 方法。 2) 当我们在 Cartheader 类中新建一个税类时,我们并没有更新该税类的自定义实例,因此不使用自定义代码。
目标如下: 1) 提供具有“正常”功能的基本税类。 2) 允许用户覆盖 Web 应用的 app_code 文件夹中的税类,以创建新的逻辑来计算税款。它仍将具有与原始签名相同的输入和输出签名。 3) cartheader.UpdateCartStep2 方法必须能够从基类或重写的自定义类(如果它被重写)访问 wa_cc_calctax 函数。
在这个示例中,我们显然已经破解了它并将自定义版本的税类 (CustomTax) 作为参数传递到 UpdateCartStep2 方法中。这是我们根据此处的建议实施的解决方法……但是我们知道这不是“正确”的方法。
【问题讨论】:
-
使用类似 base.SaveCart() 的东西?
标签: vb.net class interface methods overriding