2012-01-31 56 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

相关问题