Создайте сервис WCF для неуправляемых клиентов C++

Попробуйте это

<?php 

use Illuminate\Pagination\LengthAwarePaginator;

$transactions = Transaction::all()->groupBy(function($transaction) {
  return Carbon::parse($transaction->date)->format('m-Y'); 
});

//new LengthAwarePaginator($data,$countOfData,$perPage,$currentPage);
$transactions=new LengthAwarePaginator($transactions->forPage($currentPage,$perPage),$transactions->count(),$currentPage);

Надеюсь, это поможет ...

59
задан galets 30 March 2009 в 15:51
поделиться

4 ответа

Для тех, кому интересно, я нашел одно полурабочее решение для Сервера ATL. Следующее является кодом хоста, заметьте, что это использует BasicHttpBinding, это - единственное, которое работает с Сервером ATL:

        var svc =  new Service1();
        Uri uri = new Uri("http://localhost:8200/Service1");
        ServiceHost host = new ServiceHost(typeof(Service1), uri);

        var binding = new BasicHttpBinding();
        ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(IService1), binding, uri);
        endpoint.Behaviors.Add(new InlineXsdInWsdlBehavior());

        host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true });
        var mex = host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
        host.Open();

        Console.ReadLine();

код для InlineXsdInWsdlBehavior мог быть найден здесь. Одно важное изменение должно быть сделано к InlineXsdInWsdlBehavior для него для работы правильно с sproxy, когда составные типы включены. Это вызывается ошибкой в sproxy, который правильно не определяет объем псевдонимов пространства имен, таким образом, wsdl не может иметь повторяющихся псевдонимов пространства имен, или sproxy будет гадить. Вот функции, который должен измениться:

    public void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context)
    {
        int tnsCount = 0;

        XmlSchemaSet schemaSet = exporter.GeneratedXmlSchemas;

        foreach (WsdlDescription wsdl in exporter.GeneratedWsdlDocuments)
        {
            //
            // Recursively find all schemas imported by this wsdl
            // and then add them. In the process, remove any
            // <xsd:imports/>
            //
            List<XmlSchema> importsList = new List<XmlSchema>();
            foreach (XmlSchema schema in wsdl.Types.Schemas)
            {
                AddImportedSchemas(schema, schemaSet, importsList, ref tnsCount);
            }
            wsdl.Types.Schemas.Clear();
            foreach (XmlSchema schema in importsList)
            {
                RemoveXsdImports(schema);
                wsdl.Types.Schemas.Add(schema);
            }
        }
    }


    private void AddImportedSchemas(XmlSchema schema, XmlSchemaSet schemaSet, List<XmlSchema> importsList, ref int tnsCount)
    {
        foreach (XmlSchemaImport import in schema.Includes)
        {
            ICollection realSchemas = schemaSet.Schemas(import.Namespace);
            foreach (XmlSchema ixsd in realSchemas)
            {
                if (!importsList.Contains(ixsd))
                {
                    var new_namespaces = new XmlSerializerNamespaces();
                    foreach (var ns in ixsd.Namespaces.ToArray())
                    {
                        var new_pfx = (ns.Name == "tns") ? string.Format("tns{0}", tnsCount++) : ns.Name;
                        new_namespaces.Add(new_pfx, ns.Namespace);
                    }

                    ixsd.Namespaces = new_namespaces;
                    importsList.Add(ixsd);
                    AddImportedSchemas(ixsd, schemaSet, importsList, ref tnsCount);
                }
            }
        }
    }

Следующий шаг должен генерировать заголовок C++:

sproxy.exe /wsdl http://localhost:8200/Service1?wsdl

и затем программа C++ похожа на это:

using namespace Service1;

CoInitializeEx( NULL, COINIT_MULTITHREADED  );

{
    CService1T<CSoapWininetClient> cli;
    cli.SetUrl( _T("http://localhost:8200/Service1") );

    HRESULT hr = cli.HelloWorld(); //todo: analyze hr
}

CoUninitialize();
return 0;

Получающийся код C++ обрабатывает составные типы довольно прилично, за исключением того, что он не может присвоить ПУСТОЙ УКАЗАТЕЛЬ объектам.

12
ответ дан galets 24 November 2019 в 18:31
поделиться

Основная идея состоит в том, чтобы написать код WCF для Ваших клиентов в C# (это просто легче этот путь), и используйте мост C++ dll для устранения разрыва между неуправляемым кодом C++ и управляемым кодом WCF, написанным в C#.

Вот пошаговый процесс с помощью Visual Studio 2008 наряду с.NET 3,5 SP1.

  1. Первое, что нужно сделать, создают Сервис WCF и средство разместить его. Если у Вас уже есть это, пропустите к Шагу 7 ниже. Иначе создайте Сервис Windows NT, выполняющий шаги отсюда. Используйте имена по умолчанию, предлагаемые VS2008 для проекта и любых классов, которые добавляются к проекту. Этот Сервис Windows NT разместит Сервис WCF.

    • Добавьте Сервис WCF под названием HelloService к проекту. Чтобы сделать это, щелкните правой кнопкой по проекту в окне Solution Explorer и выберите Объект Add|New... пункт меню. В Добавлении Нового диалогового окна Объекта выберите шаблон C# WCF Service и нажмите кнопку Add. Это добавляет HelloService к проекту в форме интерфейсного файла (IHelloService.cs), файл класса (HelloService.cs) и сервисный конфигурационный файл по умолчанию (app.config).

    • Определите HelloService как это:

``

    [ServiceContract]
    public interface IHelloService
    {
        [OperationContract]
        string SayHello(string name);
    }
    public class HelloService : IHelloService
    {
        public string SayHello(string name)
        {
            return String.Format("Hello, {0}!", name);
        }
    }
  • Измените класс Service1, созданный на Шаге 1 выше для сходства с этим:

    using System.ServiceModel;
    using System.ServiceProcess;
    public partial class Service1 : ServiceBase
    {
        private ServiceHost _host;
        public Service1()
        {
            InitializeComponent();
        }
        protected override void OnStart( string [] args )
        {
            _host = new ServiceHost( typeof( HelloService ) );
            _host.Open();
        }
        protected override void OnStop()
        {
            try {
                if ( _host.State != CommunicationState.Closed ) {
                    _host.Close();
                }
            } catch {
            }
        }
    }
    
  • Разработайте проект.

  • Откройте командную строку Visual Studio 2008 года. Перейдите к выходному каталогу для проекта. Введите следующее: 'installutil WindowsService1.exe' Это устанавливает Сервис Windows NT на Вашу локальную машину. Откройте Сервисную панель управления и запустите сервис Service1. Важно сделать это для Шага 9 ниже для работы.

    1. Откройте другой экземпляр Visual Studio 2008 и создайте приложение MFC, которое является почти так далеко, как можно добраться от WCF. Как пример, я просто создал диалоговое приложение MFC и добавил мнение Привет! кнопка к нему. Щелкните правой кнопкой по проекту в Проводнике Решения и выберите пункт меню Properties. При настройках General измените Выходной Каталог на..\bin\Debug. При настройках General C/C++ добавьте..\HelloServiceClientBridge к Дополнительному, Включают Каталоги. При настройках Linker General добавьте..\Debug к Дополнительным Каталогам Библиотеки. Нажмите кнопку OK.
  • Из меню File выберите Проект Add|New... пункт меню. Выберите шаблон C# Class Library. Измените имя на HelloServiceClient и нажмите кнопку OK. Щелкните правой кнопкой по проекту в Проводнике Решения и выберите пункт меню Properties. На вкладке Build измените выходной путь к..\bin\Debug так блоку, и app.config файл будет в том же каталоге как приложение MFC. Эта библиотека будет содержать сервисную ссылку, т.е. прокси-класс WCF, к WCF Привет Сервис, размещенный в Сервисе Windows NT.

  • В Проводнике Решения щелкните правой кнопкой по папке References для проекта HelloServiceClient и выберите Добавить Сервисную Ссылку... пункт меню. В Поле адреса введите адрес Привет Сервиса. Это должно быть равно базовому адресу в app.config файле, созданном на Шаге 2 выше. Нажмите кнопку Go. Привет Сервис должен обнаружиться в Сервисном списке. Нажмите кнопку OK для автоматической генерации прокси-класса (прокси-классов) для Привет Сервис.Примечание: Я, кажется, всегда сталкиваюсь с проблемами компиляции с файлом Reference.cs, сгенерированным этим процессом. Я не знаю, делаю ли я его неправильно или если существует ошибка, но самый легкий способ зафиксировать, это, изменяют файл Reference.cs непосредственно. Проблема обычно является проблемой пространства имен и может быть решена с минимальным усилием. Просто знайте, что это - возможность. Для этого примера я изменил HelloServiceClient. ServiceReference1 только к HelloService (наряду с любыми другими необходимыми изменениями).

  • Чтобы позволить Приложению MFC взаимодействовать с сервисом WCF, мы должны создать "мост" управляемого С++ DLL. Из меню File выберите Проект Add|New... пункт меню. Выберите шаблон Win32 Project C++. Измените имя на HelloServiceClientBridge и нажмите кнопку OK. Для Параметров настройки приложения измените Тип приложения на DLL и проверьте Пустой флажок проекта. Нажмите кнопку Finish.

  • Первое, что нужно сделать, изменяют свойства проекта. Щелкните правой кнопкой по проекту в Проводнике Решения и выберите пункт меню Properties. При настройках General измените Выходной Каталог на..\bin\Debug и измените Вариант поддержки Общеязыковой среды выполнения на Поддержку Общеязыковой среды выполнения (/сброс). При настройках Framework и References добавьте ссылку на Систему.NET, Систему. ServiceModel и mscorlib блоки. Нажмите кнопку OK.

  • Добавьте следующие файлы к проекту HelloServiceClientBridge - HelloServiceClientBridge.h, IHelloServiceClientBridge.h и HelloServiceClientBridge.cpp.

  • Измените IHelloServiceClientBridge.h для сходства с этим:

    #ifndef __IHelloServiceClientBridge_h__
    #define __IHelloServiceClientBridge_h__
    
    #include <string>
    
    #ifdef HELLOSERVICECLIENTBRIDGE_EXPORTS
    #define DLLAPI __declspec(dllexport)
    #else
    #define DLLAPI __declspec(dllimport)
    #pragma comment (lib, "HelloServiceClientBridge.lib") // if importing, link also
    #endif
    
    class DLLAPI IHelloServiceClientBridge
    {
    public:
        static std::string SayHello(char const *name);
    };
    
    #endif // __IHelloServiceClientBridge_h__
    
  • Измените HelloServiceClientBridge.h для сходства с этим:

    #ifndef __HelloServiceClientBridge_h__
    #define __HelloServiceClientBridge_h__
    
    #include <vcclr.h>
    #include "IHelloServiceClientBridge.h"
    
    #ifdef _DEBUG
    #using<..\HelloServiceClient\bin\Debug\HelloServiceClient.dll>
    #else
    #using<..\HelloServiceClient\bin\Release\HelloServiceClient.dll>
    #endif
    
    class DLLAPI HelloServiceClientBridge : IHelloServiceClientBridge
    { };
    
    #endif // __HelloServiceClientBridge_h__
    
  • Синтаксис для .cpp файла использует управляемый С++, который берет некоторых привыкающих к. Измените HelloServiceClientBridge.cpp для сходства с этим:

    #include "HelloServiceClientBridge.h"
    
    using namespace System;
    using namespace System::Runtime::InteropServices;
    using namespace System::ServiceModel;
    using namespace System::ServiceModel::Channels;
    
    std::string IHelloServiceClientBridge::SayHello(char const *name)
    {
        std::string rv;
        gcroot<Binding^> binding = gcnew WSHttpBinding();
        gcroot<EndpointAddress^> address = gcnew EndpointAddress(gcnew String("http://localhost:8731/Design_Time_Addresses/WindowsService1/HelloService/"));
        gcroot<HelloService::HelloServiceClient^> client = gcnew HelloService::HelloServiceClient(binding, address);
        try {
            // call to WCF Hello Service
            String^ message = client->SayHello(gcnew String(name));
            client->Close();
            // marshal from managed string back to unmanaged string
            IntPtr ptr = Marshal::StringToHGlobalAnsi(message);
            rv = std::string(reinterpret_cast<char *>(static_cast<void *>(ptr)));
            Marshal::FreeHGlobal(ptr);
        } catch (Exception ^) {
            client->Abort();
        }
        return rv;
    }
    
  • Единственная вещь, оставленная сделать, обновить приложение MFC для вызова SayHello () служебный вызов WCF. На форме MFC дважды щелкните по Say Hello! кнопка для генерации обработчика событий ButtonClicked. Заставьте обработчик событий быть похожим на это:

    #include "IHelloServiceClientBridge.h"
    #include <string>
    void CMFCApplicationDlg::OnBnClickedButton1()
    {
        try {
            std::string message = IHelloServiceClientBridge::SayHello("Your Name Here");
            AfxMessageBox(CString(message.c_str()));
        } catch (...) {
        }
    }
    
  • Запустите приложение и нажмите Say Hello! кнопка. Это заставит приложение вызывать SayHello () метод WCF Привет Сервис, размещенный в Сервисе Windows NT (который должен все еще работать, между прочим). Возвращаемое значение затем отображено в окне сообщения.

Надо надеяться, можно экстраполировать от этого простого примера для установки потребностям. Если это не работает, сообщите мне, таким образом, я могу исправить сообщение.

58
ответ дан Community 24 November 2019 в 18:31
поделиться

Я создал бы управляемый класс C#, чтобы сделать, WCF работают и выставляют класс как COM-объект клиентам C++.

2
ответ дан kenny 24 November 2019 в 18:31
поделиться

Можно реализовать клиент SOAP несколько легко использование Инструментария Мыла MS устаревшего. К сожалению, кажется, нет замены для этого за пределами перемещения в.NET.

1
ответ дан Eclipse 24 November 2019 в 18:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: