Помощь Перевод небольшого приложения C # WCF в Visual Basic (часть 2) - PullRequest
2 голосов
/ 18 октября 2010

Я недавно задал вопрос о переводе примера кода, который я нашел в Интернете, из C # в VB, и мне дали ссылки на сайты, которые автоматизируют перевод кода (http://converter.telerik.com/ & http://www.developerfusion.com/tools/convert/csharp-to-vb/). Я очень нов VB и, к сожалению, VB, который вернули переводчики, не компилируется в Visual Studio 2010. Я надеюсь, что кто-нибудь может помочь мне исправить неработающую часть кода VB.

Вот код C #, который я конвертирую в 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;
            }
        }
    }
}

Оба преобразователя, которые я перечислил выше, возвращают один и тот же код VB. Часть кода VB, которая не работает, находится в методе AddMessage. Вот код VB, который генерирует переводчик:

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

Если бы кто-то мог помочь мне исправить код VB для метода AddMessage, я был бы очень признателен. Спасибо!

Ответы [ 2 ]

1 голос
/ 19 октября 2010

Этот код работает:

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
1 голос
/ 19 октября 2010

Я не большой программист VB.NET, но я думаю, что ясно, что синтаксический анализатор C # -> VB.NET не может справиться с этим трюком делегата.То, что происходит в коде, на самом деле довольно просто, если вы удалите этот уровень сложности с делегатом (который выглядит простым, только когда вы полностью его понимаете).В конце концов, код C # просто просматривает список подписчиков и вызывает их.Вероятно, причиной использования делегата была возможность удаления из той же коллекции, что и итеративная, без необходимости сохранять их в другой конструкции.

Здесь я просто добавляю подписчиков, которых нужно удалить, в другой список, а затем перебираю их, удаляя из оригинала (не проверено):

    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
...