传递具有多个约束作为参数的泛型类

时间:2015-10-14 08:29:55

标签: vb.net generics

我正在开发一个vb.net迁移项目..project有一些核心dll..core dlls根据更新需要重新编写包装类

现有的dll代码:

 public abstract class BusinessService : IPayload, IPayload2, IParserContext 

现有代码

 Public Sub Execute(ByVal pBs As BusinessService, ByVal pExecuteMode As ExecuteModes)
        If pExecuteMode = ExecuteModes.AwaitAsynchronous Then
            Me.Execute(pBs, Me.AWAIT_TIME_IN_MILLISEC)
        Else
            mStartTime = Now()
            mBsExecuterHelper = New BsExecuterHelper
            mBsExecuterHelper.Execute(pBs, pExecuteMode)
        End If
    End Sub

新的Dll代码:

public class BusinessService<TRequest, TResponse> : 
    IBusinessService where TRequest : BsRequest, new() where TResponse : BsResponse, new()
  {

  }

现在我需要将BusinessService作为参数传递给现有代码。我在这里可以帮助我如何将泛型类作为带有多个约束的参数传递

2 个答案:

答案 0 :(得分:0)

Public Class BsExecuter
    Private WithEvents mAwaitTimer As System.Windows.Forms.Timer
    Private Const AWAIT_TIME_IN_MILLISEC As Integer = 50
    Private WithEvents mBsExecuterHelper As BsExecuterHelper
    Public Delegate Sub CallBackMethod(ByVal pBusinessService As BusinessService, ByVal pException As Exception)
    Public Event BsExecuted(ByVal pBsExecuter As BsExecuter, ByVal pBusinessService As BusinessService, ByVal pException As System.Exception)
    Private mStartTime, mEndTime As Date
    Private mLogger As ILog
    Enum ExecuteModes
        Synchronous = 1
        Asynchronous = 2
        AwaitAsynchronous = 3
    End Enum
    Enum ExecuteStates
        NotStarted = 1
        Running = 2
        Finnished = 3
        Cancelled = 4
    End Enum
    Public Sub Execute(ByVal pBs As BusinessService)
        Me.Execute(pBs, ExecuteModes.Synchronous)
    End Sub
    Public Sub Execute(ByVal pBs As BusinessService, ByVal pExecuteMode As ExecuteModes)
        If pExecuteMode = ExecuteModes.AwaitAsynchronous Then
            Me.Execute(pBs, Me.AWAIT_TIME_IN_MILLISEC)
        Else
            mStartTime = Now()
            mBsExecuterHelper = New BsExecuterHelper
            mBsExecuterHelper.Execute(pBs, pExecuteMode)
        End If
    End Sub
    Public Sub Execute(ByVal pBs As BusinessService, ByVal pAwaitTimeInMillisec As Integer)
        mBusinessService = pBs
        mAwaitTimer = New System.Windows.Forms.Timer
        mAwaitTimer.Enabled = True
        mAwaitTimer.Interval = pAwaitTimeInMillisec
        Debug.WriteLine("Called: " & Now().ToString("ss.ffff"))
        mAwaitTimer.Start()
    End Sub
    Private Sub mAwaitTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles mAwaitTimer.Tick
        mAwaitTimer = Nothing
        Debug.WriteLine("Starts: " & Now().ToString("ss.ffff"))
        mStartTime = Now()
        mBsExecuterHelper = New BsExecuterHelper
        mBsExecuterHelper.Execute(mBusinessService, ExecuteModes.Asynchronous)
        mBusinessService = Nothing
    End Sub
    Public Sub Execute(ByVal pBs As BusinessService, ByVal pAddressOfCallbackMethod As CallBackMethod)
        Me.Execute(pBs, pAddressOfCallbackMethod, ExecuteModes.Synchronous)
    End Sub
    Public Sub Execute(ByVal pBs As BusinessService, ByVal pAddressOfCallbackMethod As CallBackMethod, ByVal pExecuteMode As ExecuteModes)
        mStartTime = Now()
        mBsExecuterHelper = New BsExecuterHelper
        mBsExecuterHelper.Execute(pBs, pAddressOfCallbackMethod, pExecuteMode)
    End Sub
    Public Sub Cancel()
        mBsExecuterHelper.ExecuteState = ExecuteStates.Cancelled
    End Sub
    Private Sub mBsExecuterHelper_BsExecuted(ByVal pBusinessService As BusinessService, ByVal pException As System.Exception) Handles mBsExecuterHelper.BsExecuted
        mEndTime = Now()
        Me.LogBusinessService(pBusinessService)
        RaiseEvent BsExecuted(Me, pBusinessService, pException)
    End Sub
    Private Sub mBsExecuterHelper_ExecuteCallBack(ByVal pBusinessService As BusinessService, ByVal pException As System.Exception) Handles mBsExecuterHelper.ExecuteCallBack
        mEndTime = Now()
        Me.LogBusinessService(pBusinessService)
    End Sub
    Private Sub LogBusinessService(ByVal pBusinessService As BusinessService)
        If Not (pBusinessService Is Nothing) Then
            Dim vLoggString As String = ""
            Dim vExecTime As TimeSpan
            Dim vExecTimeInSek As Double
            mLogger = LogManager.GetLogger(pBusinessService.GetServiceName())

            vExecTime = mEndTime.Subtract(mStartTime)
            vExecTimeInSek = vExecTime.Milliseconds / 1000
            'vLoggString = "Start:" & mStartTime.ToString("HH:mm:ss,ffff") & " End:" & mEndTime.ToString("HH:mm:ss,ffff")
            vLoggString = "ExecutionTime:" & vExecTimeInSek.ToString("#####0.0") & "s"
            vLoggString &= " User:" & Environment.UserName
            vLoggString &= " Request:" & pBusinessService.GetRequestXml()
            mLogger.Info(vLoggString)
        End If
    End Sub
#Region " BsExecuterHelper "
    Private Class BsExecuterHelper
#Region "Used by main thread"
        Private mThread As Thread
        Private mExecuteModes As ExecuteModes
        Private mCallBackMethod As CallBackMethod
        Shared Sub New()
            SharedTimer = New System.Windows.Forms.Timer
            SharedTimer.Enabled = True
            SharedTimer.Interval = 70
        End Sub
        Public Event BsExecuted(ByVal pBusinessService As BusinessService, ByVal pException As System.Exception)
        Public Event ExecuteCallBack(ByVal pBusinessService As BusinessService, ByVal pException As System.Exception)
        Private Sub mPrivateTimerReference_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles mPrivateTimerReference.Tick
            mPrivateTimerReference = Nothing
            If Not mCallBackMethod Is Nothing Then
                RaiseEvent ExecuteCallBack(mBs, mException)
                mCallBackMethod(mBs, mException)
            Else
                RaiseEvent BsExecuted(mBs, mException)
            End If
        End Sub
        Public Sub Execute(ByVal pBs As BusinessService, ByVal pExecuteMode As ExecuteModes)
            mBs = pBs
            mExecuteModes = pExecuteMode
            ExecuteState = ExecuteStates.Running
            If pExecuteMode = ExecuteModes.Synchronous Then
                RunBs()
            Else
                mThread = New Thread(AddressOf RunBs)
                mThread.Name = "BsExecuter"
                mThread.IsBackground = True
                mThread.Start()
            End If
        End Sub
        Public Sub Execute(ByVal pBs As BusinessService, ByVal pAddressOfCallbackMethod As CallBackMethod, ByVal pExecuteMode As ExecuteModes)
            mCallBackMethod = pAddressOfCallbackMethod
            Me.Execute(pBs, pExecuteMode)
        End Sub
        Public Sub Cancel()
            ExecuteState = ExecuteStates.Cancelled
        End Sub
#End Region
#Region "Used by new sub thread"
        Private Sub ServiceExecuted()
            If mExecuteModes = ExecuteModes.Synchronous Then
                If Not mCallBackMethod Is Nothing Then
                    RaiseEvent ExecuteCallBack(mBs, mException)
                    mCallBackMethod(mBs, mException)
                Else
                    RaiseEvent BsExecuted(mBs, mException)
                End If
            Else
                mPrivateTimerReference = SharedTimer
            End If
        End Sub
        Private Sub RunBs()
            Dim vException As Exception = Nothing
            Try
                'Use INAF EbcHandler to mock BS calls and for error handling translation
                IKEA.Framework.DomainModel.Context.ServiceContext.EbcHandler.ExecuteBusinessService(mBs)
                'mBs.Execute()
            Catch e As Exception
                vException = e
            Finally
                If Not ExecuteState = ExecuteStates.Cancelled Then
                    ExecuteState = ExecuteStates.Finnished
                    mException = vException
                    ServiceExecuted()
                End If
            End Try
        End Sub
#End Region
#Region "Shared between the threads"
        Private Shared SharedTimer As System.Windows.Forms.Timer
        Private mBs As BusinessService
        Private mException As System.Exception = Nothing
        Private WithEvents mPrivateTimerReference As System.Windows.Forms.Timer
        Public Event ExecuteStateChanged()
        Private mExecuteState As ExecuteStates = ExecuteStates.NotStarted
        Public Property ExecuteState() As ExecuteStates
            Get
                Return mExecuteState
            End Get
            Set(ByVal Value As ExecuteStates)
                mExecuteState = Value
                RaiseEvent ExecuteStateChanged()
            End Set
        End Property
#End Region
    End Class
#End Region
End Class

答案 1 :(得分:0)

假设您希望将Execute方法设为通用,并且能够接受通用BusinessService作为输入,则方法签名应如下所示:

Public Sub Execute(Of TRequest As {New, BsRequest}, TResponse As {New, BsResponse})(
                    ByVal pBs As BusinessService(Of TRequest, TResponse),
                    ByVal pExecuteMode As ExecuteModes)

End Sub

当然,这需要对您班级中的其他方法进行类似的更改。

您可能还决定让整个班级变得像这样:

Public Class BsExecuter(Of TRequest As {New, BsRequest}, TResponse As {New, BsResponse})

    Public Sub Execute(
                    ByVal pBs As BusinessService(Of TRequest, TResponse),
                    ByVal pExecuteMode As ExecuteModes)

    End Sub
End Class

请注意,在这种情况下,该方法已经是通用的,您不需要在方法上指定泛型约束,因为它们已经为类设置了。

如果您不需要您的方法是通用的,例如,您可能希望您的方法处理特定的BusinessService(例如BusinessService(Of MyRequest, MyResponse)),您可以这样做:

假设这些是您的特殊BsRequestBsResponse类:

Public Class MyRequest
    Inherits BsRequest

End Class

Public Class MyResponse
    Inherits BsResponse

End Class

然后你不需要做任何通用的,只是你可以接受你想要的特定类型:

Public Sub Execute(
                    ByVal pBs As BusinessService(Of MyRequest, MyResponse),
                    ByVal pExecuteMode As ExecuteModes)

End Sub