File: NamedPipeMetadataImporter.cs
Web Access
Project: src\src\dotnet-svcutil\lib\Microsoft.Svcutil.NamedPipeMetadataImporter\Microsoft.Svcutil.NamedPipeMetadataImporter.csproj (Microsoft.Svcutil.NamedPipeMetadataImporter)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Threading.Tasks;
using System.Xml;
 
namespace Microsoft.Tools.ServiceModel.Svcutil
{
    public class NamedPipeMetadataImporter
    {
        const string UriSchemeNetPipe = "net.pipe";
        const string NamedPipeBindingName = "MetadataExchangeNamedPipeBinding";
        const string BindingNamespace = "http://schemas.microsoft.com/ws/2005/02/mex/bindings";
 
#if NET6_0_OR_GREATER
        [System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif
        public XmlReader GetReader(Uri uri)
        {
            return GetMetadatadataAsync(uri).GetAwaiter().GetResult();
        }
 
#if NET6_0_OR_GREATER
        [System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif
        public async Task<XmlReader> GetMetadatadataAsync(Uri uri)
        {
            if (uri.Scheme != UriSchemeNetPipe)
            {
                return null;
            }
 
            ChannelFactory<IMetadataExchange> factory = new ChannelFactory<IMetadataExchange>(CreateNamedPipeBinding(), new EndpointAddress(uri.AbsoluteUri));
            IMetadataExchange proxy = factory.CreateChannel();
            MessageVersion messageVersion = factory.Endpoint.Binding.MessageVersion;
            var tcs = new TaskCompletionSource<XmlReader>();
            try
            {
                var _message = Message.CreateMessage(messageVersion, WSTransfer.GetAction);
                IAsyncResult result = proxy.BeginGet(_message, new AsyncCallback(ar =>
                {
                    try
                    {
                        RequestCallback(ar, tcs);
                    }
                    catch (Exception ex)
                    {
                        tcs.SetException(ex);
                    }
                }), proxy);
 
                while (!result.IsCompleted)
                {
                    await Task.Delay(100);
                }
            }
            catch (Exception ex)
            {
                ((IClientChannel)proxy).Close();
                tcs.SetException(ex);
            }
 
            finally
            {
                ((IClientChannel)proxy).Abort();
            }
 
            return await tcs.Task;
        }
 
        public void RequestCallback(IAsyncResult result, TaskCompletionSource<XmlReader> tcs)
        {
            if (result.CompletedSynchronously)
                return;
 
            if (result.AsyncState is IMetadataExchange metadataClient)
            {
                try
                {
                    Message response = metadataClient.EndGet(result);
                    if (!response.IsFault)
                    {
                        XmlReader xmlReader = response.GetReaderAtBodyContents();
                        tcs.SetResult(xmlReader);
                    }
                    else
                    {
                        // Handle fault response
                        tcs.SetException(new Exception("Fault response received."));
                    }
                }
                catch (Exception ex)
                {
                    tcs.SetException(ex);
                }
            }
        }
 
#if NET6_0_OR_GREATER
        [System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif
        public CustomBinding CreateNamedPipeBinding()
        {
            CustomBinding binding = new CustomBinding(NamedPipeBindingName, BindingNamespace);
            NamedPipeTransportBindingElement pipeTransport = new NamedPipeTransportBindingElement();
            binding.Elements.Add(pipeTransport);
            return binding;
        }
    }
}