Paul Lemke
Paul Lemke

Reputation: 5534

How to convert delegate from c# to vb.net?

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?

Upvotes: 2

Views: 3359

Answers (5)

GregC
GregC

Reputation: 8007

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

Upvotes: 6

Rune FS
Rune FS

Reputation: 21742

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

Upvotes: 1

Joel Coehoorn
Joel Coehoorn

Reputation: 415735

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.

Upvotes: 8

Paul Lemke
Paul Lemke

Reputation: 5534

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!

Upvotes: 1

Muad&#39;Dib
Muad&#39;Dib

Reputation: 29216

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

Upvotes: 0

Related Questions