2012-01-31 69 views
0

我正在與一個第三方庫進行連接,這個第三方庫連接到一個舊的數據庫系統。有一種方法 - CallProg,稱爲「存儲過程」(缺乏更好的翻譯 - 人羣中的任何Pick用戶?)。然而,而不是做這樣的事情:將20個過載的子文件合併爲一個文件

Public Sub CallProg(ProgName, ParamArray ProgArgs() As String) 
    ... 
End Sub 

,甚至這樣的:

Public Sub CallProg(ProgName, Optional Arg1 As String, Optional Arg2 As String ... Optional Arg20 As String) 

他們這樣做:

Public Sub CallProg(ProgName) 
Public Sub CallProg(ProgName, Arg1 As String) 
Public Sub CallProg(ProgName, Arg1 As String, Arg2 As String) 
Public Sub CallProg(ProgName, Arg1 As String, Arg2 As String, Arg3 As String) 
... 
Public Sub CallProg(ProgName, Arg1 As String, ... Arg20 As String) 

我正在寫一個抽象類來處理登錄,設置環境等等,所以它可以在許多其他項目中用作通用的「幫手」類。有什麼辦法可以包裝CallProg的sub,不涉及20個重載?

+0

你描述的'Optional'選項有什麼問題? – Oded 2012-01-31 20:53:03

+0

如果我使用20個可選項做了我的幫手例程,那麼我在'Select Case'語句中仍然必須有20個'Case'行。我無法調用帶有1個「真實」參數和20個空白字符串的底層'CallProg' sub,因爲它會嘗試將所有20個參數傳遞給只需要一個參數的後端程序。 – mounty 2012-01-31 21:02:52

+0

我想你可以使用反射。 – 2012-01-31 21:13:31

回答

0

這是一個非常快速的想法,如何使用反射做到這一點。我不知道,如果它的最好的方式,但它應該工作...

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 

    CallProg("ProgName", {"testArg1", "TestArg2"}) 

End Sub 

Private Sub CallProg(ByVal ProgName As String, ByVal Params As IEnumerable(Of String)) 

    Dim testClass As New Test1 

    Dim methodTypes As List(Of Type) = 
     Params.Select(Function(x) GetType(String)).ToList 

    methodTypes.Add(GetType(String)) 

    Dim methodToBeCalled As Reflection.MethodInfo = 
     testClass.GetType.GetMethod("CallProg", 
            System.Reflection.BindingFlags.Instance Or System.Reflection.BindingFlags.Public, 
            Type.DefaultBinder, 
            methodTypes.ToArray, 
            Nothing) 


    Dim paramsToPass As New List(Of String) 

    paramsToPass.Add(ProgName) 
    paramsToPass.AddRange(Params) 

    methodToBeCalled.Invoke(testClass, paramsToPass.ToArray) 

End Sub 

末級

公共類的Test1

Public Sub CallProg(ByVal ProgName As String) 
    Debug.WriteLine("Sub0 called") 
End Sub 

Public Sub CallProg(ByVal ProgName As String, ByVal Arg1 As String) 
    Debug.WriteLine("Sub1 called") 
End Sub 

Public Sub CallProg(ByVal ProgName As String, ByVal Arg1 As String, ByVal Arg2 As String) 
    Debug.WriteLine("Sub2 called") 
End Sub 

Public Sub CallProg(ByVal ProgName As String, ByVal Arg1 As String, ByVal Arg2 As String, ByVal Arg3 As String) 
    Debug.WriteLine("Sub3 called") 
End Sub 

末級

+0

這大致是什麼結束了工作;我會發布我最終的結果。 – mounty 2012-02-01 19:23:10

0

另一種方式按照Rene147的建議:

Private _act As New APIClass 

Public Sub CallProg(ByVal ProgName As String, ByVal ParamArray ProgArgs() As String) 
    Try 
     Dim tList As New List(Of Type) 
     tList.Add(GetType(String)) 

     Dim aList As New List(Of String) 
     aList.Add(ProgName) 

     For Each arg In ProgArgs 
      tList.Add(GetType(String).MakeByRefType) 
      'tList.Add(GetType(String)) <-- only use this if all the args are ByVal 
      aList.Add(arg) 
     Next 
     Dim typeList As Type() = tList.ToArray 
     Dim argList As String() = aList.ToArray 

     GetType(APIClass).GetMethod("CallProg", typeList).Invoke(_act, argList) 
    Catch ex As Exception 
     Console.Write("Error running program {0}.", ProgName) 
    End Try 
End Sub 
+0

捕捉異常並顯示錯誤是毫無意義的。拋出異常時您會看到錯誤消息。 – 2012-02-02 18:14:34

+0

實際上,在這種情況下,由於我們正在使用一次只允許5個連接的連接管理器(某些許可問題),如果我正在調試並遇到異常並且必須重置該程序,那麼很痛苦去連接管理器並關閉我手動使用的連接。通過捕獲異常,我可以讓類正常註銷(此處未顯示),而不是中止連接。但我同意 - 在正常情況下,這是不必要的。 – mounty 2012-02-02 18:55:59

+0

奇怪。它不知道程序是關閉的*?時間轉換組件,這顯然是一個死衚衕。無論哪種方式,我都不會在這種與黑客無關的SO回答中包含像這樣的黑客...... – 2012-02-03 02:21:17

相關問題