Для тех, кто заинтересован, я нашел одно полурабочее решение ATL-сервера. Ниже хост-код, обратите внимание, он использует BasicHttpBinding, это единственный, который работает с ATL Server:
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 можно найти here. Одно важное изменение необходимо сделать для 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++ код обрабатывает комплекс типы довольно прилично, за исключением того, что он не может назначить NULL для объектов.
Извините за задержку. Я обновил свой ответ. Надеюсь, поможет. –
Вы можете изменить службу WCF для предоставления как конечных точек SOAP, так и REST, а затем использовать конечную точку REST из C++. (Пока ваши типы данных легко анализируются на C++). См. Http://stackoverflow.com/questions/186631/rest-soap-endpoints-for-a-wcf-service –