views:

941

answers:

5

I have this code i'm trying to convert from C# to VB.net:

public object Invoke(object instance, object[] inputs, out object[] outputs)
        {
            // Create a new, STA thread
            object[] staOutputs = null;
            object retval = null;
            Thread thread = new Thread(
                delegate(){
                    retval = _innerInvoker.Invoke(instance, inputs, out staOutputs);
                });
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();
            outputs = staOutputs;
            return retval;
        }

The whole delegate thing is throwing me off. Can anyone help me convert this? Or is there an article that explains how to do it?

A: 

there is an online C# to VB converter (and vice-versa) located at http://converter.telerik.com/

I pasted your code in there....I dont know if this is valid VB or if it will work or not, but you can give it a shot.

Public Function Invoke(instance As Object, inputs As Object(), ByRef outputs As Object()) As Object
    ' Create a new, STA thread
    Dim staOutputs As Object() = Nothing
    Dim retval As Object = Nothing
    Dim thread As New Thread(Function() Do
     retval = _innerInvoker.Invoke(instance, inputs, staOutputs)
    End Function)
    thread.SetApartmentState(ApartmentState.STA)
    thread.Start()
    thread.Join()
    outputs = staOutputs
    Return retval
End Function
Muad'Dib
It won't work.
Joel Coehoorn
Agreed, first place i went was a c# to vb.net converter. it basically threw me an error: VB does not support anonymous methods/lambda expressions with a statement body
Paul Lemke
+8  A: 

It's an anonymous function, and VB.Net does not support anonymous functions like that (assuming .Net 2.0, since in .Net 3.5 that would be written as a lambda expression).

The best you can do in VB.Net is add the anonymous function (the delegate) as a separate method in the same class and use the AddressOf operator to reference this new method.


Update:
Reading your code again, the translation is complicated because your anonymous method will be interpreted as a closure, and that means the C# compiler does a complicated transformation on the code before turning it into IL; a whole new class is created is to capture (close over) the local variables referred to in the method:

Class InnerInvokerClosure
    Public instance As Object
    Public inputs() As Object
    Public staOutputs() As Object
    Public retValue As Object

    Public _innerInvoker As SomeDelegateType

    Sub New(ByRef instance as Object, ByRef inputs() as Object, ByRef staOutputs() As Object, ByRef retValue As Object, ByRef _innerInvoker As SomeDelegateType)
        Me.instance = instance
        Me.inputs = inputs
        Me.staOoutputs = staOutputs
        Me.retValue = retValue

        Me._innerInvoker = _innerInvoker
    End Sub

    Public Function Invoke() As Object
        retValue = _innerInvoker.Invoke(instance, inputs, staOutputs);
    End Function

End Class

Public Function Invoke(ByVal instance As Object, ByVal inputs() as Object, ByRef outputs() As Object) As Object
    Dim closure As New InnerInvokerClosure(instance, inputs, Nothing, Nothing, _innerInvoker)

    Dim t As New Thread(AddressOf closure.Invoke)
    t.SetApartmentState(ApartmentState.STA)
    t.Start()
    t.Join()

    outputs = closure.staOutputs
    return closure.retValue      
End Function

Note that this translation is untested and probably wrong: the exact transformation can be very complicated.

Joel Coehoorn
Can you give me an example in some sudo code? Still having a hard time wrapping my head around this...
Paul Lemke
+6  A: 

My fav way to do this is to compile in C#, and then use reflector to see what it looks like in other dotNET languages.

Friend Class Program
' Methods
Private Shared Function Foo(ByVal instance As Object, ByVal inputs As Object(), <Out> ByRef outputs As Object()) As Object
    outputs = Nothing
    Return Nothing
End Function

Public Function Invoke(ByVal instance As Object, ByVal inputs As Object(), <Out> ByRef outputs As Object()) As Object
    Dim staOutputs As Object() = Nothing
    Dim retval As Object = Nothing
    Dim thread As New Thread(Function 
        retval = Me._innerInvoker.Invoke(instance, inputs, staOutputs)
    End Function)
    thread.SetApartmentState(ApartmentState.STA)
    thread.Start
    thread.Join
    outputs = staOutputs
    Return retval
End Function

' Fields
Private _innerInvoker As MyInvoker = New MyInvoker(AddressOf Program.Foo)
End Class


<CompilerGenerated> _
Private NotInheritable Class <>c__DisplayClass1
' Methods
Public Sub <Invoke>b__0()
    Me.retval = Me.<>4__this._innerInvoker.Invoke(Me.instance, Me.inputs, Me.staOutputs)
End Sub


' Fields
Public <>4__this As Program
Public inputs As Object()
Public instance As Object
Public retval As Object
Public staOutputs As Object()
End Class
GregC
+1  A: 

SOmethiong like the following ought to it: (Where _ are private fields (this is not production rdy but hope fully give you the idea)

Public Function Invoke(instance As Object, inputs As Object(), ByRef outputs As Object()) As Object
        ' Create a new, STA thread
        Dim staOutputs As Object() = Nothing
        Dim retval As Object = Nothing
        Dim thread As New Thread(AddressOf(Do))

        _instance = instance
        _inputs = inputs
        _staOutPuts = staOutputs
        thread.SetApartmentState(ApartmentState.STA)
        thread.Start()
        thread.Join()
        outputs = staOutputs
        Return retval
    End Function

    private Function Do() as Object
    Return _innerInvoker.Invoke(_instance, _inputs, _staOutputs)
    end Function
Rune FS
+1  A: 

Here is the final code i used:

    Public Function Invoke(ByVal instance As Object, ByVal inputs As Object(), ByRef outputs As Object()) As Object Implements System.ServiceModel.Dispatcher.IOperationInvoker.Invoke
        Dim staOutputs As Object() = Nothing
        Dim retval As Object = Nothing
        Dim thread As New Thread(AddressOf DoWork)
        _instance = instance
        _inputs = inputs
        _staOutPuts = staOutputs
        thread.SetApartmentState(ApartmentState.STA)
        thread.Start()
        thread.Join()
        outputs = staOutputs
        Return retval
    End Function

    Private Function DoWork() As Object
        Return _innerInvoker.Invoke(_instance, _inputs, _staOutPuts)
    End Function

@Rune FS - so close, just needed a little help. Thanks!

Paul Lemke
fyi: I updated my answer as well.
Joel Coehoorn
Never having code one single VB.NET program Im reasonably satisfied with the result lol
Rune FS