views:

65

answers:

2

Hi -

I recently asked a question about translating a code sample I found on on the internet from C# into VB and I was given links to websites that automate code translation (http://converter.telerik.com/ & http://www.developerfusion.com/tools/convert/csharp-to-vb/). I am very new to VB and unfortunately the VB that the translators returned doesn't compile in Visual Studio 2010. I am hoping someone can help me fix the non-working portion of VB code.

Here is the C# code I am converting into VB:

namespace WCFCallbacks
{
    using System;
    using System.ServiceModel;

    [ServiceContract(CallbackContract = typeof(IMessageCallback))]
    public interface IMessage
    {
        [OperationContract]
        void AddMessage(string message);

        [OperationContract]
        bool Subscribe();

        [OperationContract]
        bool Unsubscribe();
    }

    interface IMessageCallback
    {
        [OperationContract(IsOneWay = true)]
        void OnMessageAdded(string message, DateTime timestamp);
    }        
}

namespace WCFCallbacks
{
    using System;
    using System.Collections.Generic;
    using System.ServiceModel;

    public class MessageService : IMessage
    {
        private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>();

        public void AddMessage(string message)
        {

            subscribers.ForEach(delegate(IMessageCallback callback)
            {
                if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                {
                    callback.OnMessageAdded(message, DateTime.Now);
                }
                else
                {
                    subscribers.Remove(callback);
                }
            });
        }

        public bool Subscribe()
        {
            try
            {
                IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
                if (!subscribers.Contains(callback))
                    subscribers.Add(callback);
                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool Unsubscribe()
        {
            try
            {
                IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
                if (!subscribers.Contains(callback))
                    subscribers.Remove(callback);
                return true;
            }
            catch
            {
                return false;
            }
        }
    }
}

Both converters I listed above return the same VB code. The portion of VB code that doesn't work is in the AddMessage method. Here is the VB code that the translator generates:

Imports System.ServiceModel

Namespace WCFCallbacks

    <ServiceContract(CallbackContract:=GetType(IMessageCallback))> _
    Public Interface IMessage
        <OperationContract()> _
        Sub AddMessage(ByVal message As String)

        <OperationContract()> _
        Function Subscribe() As Boolean

        <OperationContract()> _
        Function Unsubscribe() As Boolean
    End Interface

    Interface IMessageCallback
        <OperationContract(IsOneWay:=True)> _
        Sub OnMessageAdded(ByVal message As String, ByVal timestamp As DateTime)
    End Interface

End Namespace

Imports System
Imports System.Collections.Generic
Imports System.ServiceModel

Namespace WCFCallbacks

    Public Class MessageService
        Implements IMessage

        Private Shared ReadOnly subscribers As New List(Of IMessageCallback)()

        Public Sub AddMessage(ByVal message As String) Implements IMessage.AddMessage

   subscribers.ForEach(Function(callback As IMessageCallback) Do
            If DirectCast(callback, ICommunicationObject).State = CommunicationState.Opened Then
                callback.OnMessageAdded(message, DateTime.Now)
            Else
                subscribers.Remove(callback)
            End If
   End Function)
  End Sub

        Public Function Subscribe() As Boolean Implements IMessage.Subscribe
            Try
                Dim callback As IMessageCallback = OperationContext.Current.GetCallbackChannel(Of IMessageCallback)()
                If Not subscribers.Contains(callback) Then
                    subscribers.Add(callback)
                End If
                Return True
            Catch
                Return False
            End Try
        End Function

        Public Function Unsubscribe() As Boolean Implements IMessage.Unsubscribe
            Try
                Dim callback As IMessageCallback = OperationContext.Current.GetCallbackChannel(Of IMessageCallback)()
                If Not subscribers.Contains(callback) Then
                    subscribers.Remove(callback)
                End If
                Return True
            Catch
                Return False
            End Try
        End Function

    End Class

End Namespace

If someone could help me by fixing the VB code for the AddMessage method I would greatly appreciate it. Thanks!

+1  A: 

I'm not much of a VB.NET programmer, but I think it's clear that the C# -> VB.NET parser is not able to handle that delegate trick. What's happening in the code is pretty basic actually, if you remove that layer of complexity with the delegate (which looks simple only when you understand it completely). In the end, the C# code is simply going through the list of subscribers and calling them. The reason for using the delegate was probably to be able to remove from the same collection as the one being iterated without having to save them in another construct.

Here, I simply add the subscribers to be removed to another list, then loop through that one deleting from the original (not tested):

    Public Sub AddMessage(ByVal message As String) Implements IMessage.AddMessage
        Dim msgCallback As IMessageCallback

        Dim removedSubscribers As New List(Of IMessageCallback)()

        For Each msgCallback In subscribers
            If (CType(msgCallback, ICommunicationObject).State = CommunicationState.Opened) Then
                msgCallback.OnMessageAdded(message, DateTime.Now)
            Else
                removedSubscribers.Add(msgCallback)
            End If
        Next

        For Each msgCallback In removedSubscribers
            subscribers.Remove(msgCallback)
        Next
    End Sub
steinar
thanks for the answer! I've also posted an alternate version that works.
MikeG
Ahh, so delegates work in VB.NET, nice to know.
steinar
+1  A: 

This code works:

Public Sub AddMessage(ByVal message As String) Implements IMessage.AddMessage

    subscribers.ForEach(Sub(callback As IMessageCallback)
                            If DirectCast(callback, ICommunicationObject).State = CommunicationState.Opened Then
                                callback.OnMessageAdded(message, DateTime.Now)
                            Else
                                subscribers.Remove(callback)
                            End If
                        End Sub)
End Sub
MikeG