2015-10-02 1 views
1

У меня есть класс, который принимает адрес метода и аргументы, и выполняет его позже, когда ему говорят об этом.Раннее связывание с generics

' need to turn option strict off due to Execute method executing late-bound code 
Option Strict Off 

Public Class WorkItem 
    Private Action As Object 
    Private Args() As Object 

    Public Overloads Sub [Set](action As Action) 
     SetArgs(action) 
    End Sub 

    Public Overloads Sub [Set](Of T)(action As Action(Of T), arg As T) 
     SetArgs(action, arg) 
    End Sub 

    Public Overloads Sub [Set](Of T1, T2)(action As Action(Of T1, T2), arg1 As T1, arg2 As T2) 
     SetArgs(action, arg1, arg2) 
    End Sub 

    '*** more overloads of [Set] method go here... 

    Private Sub SetArgs(ByVal action As Object, ParamArray args() As Object) 
     Me.Action = action 
     Me.Args = args 
    End Sub 

    Public Sub Execute() 
     '-- early binding doesn't work 
     'DirectCast(Me.Action, Action(Of T)).Invoke(Args(0)) 

     '-- this works, but forces me to to keep option strict off 
     Select Case Args.Length 
      Case 0 : Me.Action.Invoke() 
      Case 1 : Me.Action.Invoke(Args(0)) 
      Case 2 : Me.Action.Invoke(Args(0), Args(1)) 
      Case 3 : Me.Action.Invoke(Args(0), Args(1), Args(2)) 
      Case 4 : Me.Action.Invoke(Args(0), Args(1), Args(2), Args(3)) 
     End Select 
    End Sub 
End Class 

Вот некоторые тестер код:

Public Class Form1 
    Dim TheTask As WorkItem 

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click 
     TheTask = New WorkItem 
     TheTask.Set(AddressOf DummyProc, TextBox1) 
    End Sub 

    Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click 
     TheTask.Execute() 
    End Sub 

    Private Sub DummyProc(arg As TextBox) 
     Threading.Thread.Sleep(1000) 
     Debug.Print("work completed") 
    End Sub 
End Class 

WorkItem класс, очевидно, не работает с OPTION STRICT ON, в связи с поздним связыванием вызова в Execute метода.

Есть ли способ конвертировать поздний звонок для раннего связывания?

+1

Почему бы не использовать делегатов? Они созданы для такого рода занятий, нет? –

+0

Из этого фрагмента кода не нужно, чтобы 'WorkItem' знал о' Args' - у 'WorkItem' просто есть' Action' и передается ему делегат, который вызывает метод * с конкретным аргументом *. Тогда 'WorkItem.Execute' является просто' Me.Action.Invoke() '. – AakashM

+0

@ A.S.H, я согласен с делегатами, если код является общим и независимым от вызывающего. Как мне это сделать? –

ответ

1

Этого можно достичь, используя delegates. Вы можете объявить делегата, который представляет собой неэквивалентную подпрограмму, и вызвать представление этого делегата для объекта, который передал arg в качестве параметра конструктора. Я не знаю, нуждается ли в вашем решении общий рабочий элемент, реализуя его таким образом, но мой пример по-прежнему поддерживает такую ​​же настройку:

Delegate Sub WorkItem() 

Dim TheTask As WorkItem 

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
    TheTask = AddressOf (New DummyProc(Of TextBox)(TextBox1)).Execute 
End Sub 

Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click 
    TheTask.Invoke() 
End Sub 

Private Class DummyProc(Of T) 

    Private ReadOnly _arg As T 

    Public Sub New(ByVal arg As T) 
     _arg = arg 
    End Sub 

    Public Sub Execute() 
     MessageBox.Show(String.Format("My Arg: {0}", _arg)) 
     Threading.Thread.Sleep(1000) 
     MessageBox.Show("work completed") 
    End Sub 

End Class 
+0

Проблема в том, что у меня нет контроля над тем, какой метод должен быть выполнен. Он передается во время выполнения из кода пользователя в класс «WorkItem». Поэтому этот метод не решает мою проблему. –