Как создать клиентский прокси без svcutil или добавить ссылку на службу в wcf?

Как я могу создать клиентский прокси без svcutil.exe или добавить сервисную ссылку в wcf? Я хочу создать клиентский прокси во время компиляции.

wcf
12 голосов | спросил Embedd_Khurja 6 J000000Monday09 2009, 15:56:46

4 ответа


0

Если у вас есть доступ к сервисному контракту (интерфейсу IService) в отдельной DLL, вы можете добавить ссылку на эту DLL сервисного контракта, а затем сделать что-то вроде:

NetTcpBinding binding = new NetTcpBinding();
EndpointAddress address = new EndpointAddress("net.tcp://localhost:9000/YourService")

ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, address);
IService proxy = factory.CreateChannel();

и у вас есть программно созданный прокси, который вы теперь можете использовать по своему усмотрению.

ответил marc_s 6 J000000Monday09 2009, 16:27:44
0

Это может быть не то, что вы ищете, но это довольно интересно.

Vipul Modi имеет библиотеку, которая позволяет вам вызывать службы WCF после загрузки их WSDL, причем все во время выполнения.

Библиотека Vipul Modi (последняя версия)

Позволяет вам делать такие вещи:

Создайте ProxyFactory, указав URI WSDL службы.

DynamicProxyFactory factory = new DynamicProxyFactory("http://localhost:8080/WcfSamples/DynamicProxy?wsdl");

Просмотрите конечные точки, метаданные, контракты и т. д.

  • factory.Endpoints
  • factory.Metadata ​​li>
  • factory.Contracts
  • factory.Bindings

Создайте DynamicProxy для конечной точки, указав либо конечную точку, либо    название контракта.

DynamicProxy proxy = factory.CreateProxy("ISimpleCalculator");

//OR

DynamicProxy proxy = factory.CreateProxy(endpoint);

Вызов операций в DynamicProxy

double result = (double)proxy.CallMethod("Add", 1d ,2d);

Закройте DynamicProxy

proxy.Close();
ответил Anderson Imes 21 J000000Tuesday09 2009, 04:17:48
0

Вам не нужно генерировать код (или использовать файл конфигурации, полный специфики WCF).

Сначала создайте интерфейс, определяющий службу ([ServiceContract]) со всеми поддерживаемыми контрактами данных в сборке, отдельной от реализации службы.

Ссылка на сборку интерфейса в клиентской сборке.

Затем необходимо создать клиентский прокси для IMyService:

BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpoint = new EndpointAddress(url);
ChannelFactory<IMyService> chanFac = new ChannelFactory<IMyService>(binding, endpoint);
IMyService clientProxy = chanFac.CreateChannel();
ответил Richard 6 J000000Monday09 2009, 16:30:04
0

Вот решение, которое я использовал с момента появления wcf: В сборке инфраструктуры:

   internal class PerCallDisposeRealProxy<T> : RealProxy where T : class
{
    private readonly Binding _binding;
    private readonly EndpointAddress _endpointAddress;

    private static string EndpointName
    {
        get 
        {
            string endpointName = typeof(T).Name;
            if (endpointName.StartsWith("I"))
            {
                endpointName = endpointName.Substring(1);
            }
            return endpointName;
        }
    }

    internal PerCallDisposeRealProxy()
        : base(typeof(T))
    {            
    }

    internal PerCallDisposeRealProxy(Binding binding, EndpointAddress endpointAddress)
        : base(typeof(T))
    {
        if (binding == null)
            throw new ArgumentNullException("binding");
        if (endpointAddress == null)
            throw new ArgumentNullException("endpointAddress");

        _binding = binding;
        _endpointAddress = endpointAddress;
    }

    private ChannelFactory<T> CreateChannel()
    {
        if (_binding != null && _endpointAddress != null)
            return new ChannelFactory<T>(_binding, _endpointAddress);
        else
            return new ChannelFactory<T>(EndpointName);
    }

    [DebuggerStepThrough]
    public override IMessage Invoke(IMessage message)
    {
        if (message == null) throw new ArgumentNullException("message");

        //Extract method info
        var methodCall = message as IMethodCallMessage;
        Debug.Assert(methodCall != null);
        MethodInfo methodInfo = methodCall.MethodBase as MethodInfo;
        Debug.Assert(methodInfo != null);

        T channel = null;
        ChannelFactory<T> channelFactory = null;
        try
        {
            //setup channel
            try
            {
                channelFactory = CreateChannel();
            }
            catch (InvalidOperationException ex)
            {
                throw new ApplicationException(string.Format("Invalid endpoint configuration, make sure there is a servicemodel endpoint defined in configuration with the name {0}", EndpointName), ex);
            }
            channelFactory.Open();
            channel = channelFactory.CreateChannel();

            object result = methodInfo.Invoke(channel, methodCall.InArgs);
            return new ReturnMessage(result, null, 0, methodCall.LogicalCallContext, methodCall);
        }
        catch (FaultException faultException)
        {
            string msg = "FaultException: " + faultException.Message;
            MessageFault fault = faultException.CreateMessageFault();
            if (fault.HasDetail)
            {
                System.Xml.XmlReader reader = fault.GetReaderAtDetailContents();
                if (reader.Name == "ExceptionDetail")
                {
                    ExceptionDetail detail = fault.GetDetail<ExceptionDetail>();
                    msg += "\n\nStack Trace: " + detail.StackTrace;
                }
            }
            return new ReturnMessage(faultException, methodCall);
        }
        catch (TargetInvocationException targetInvocationException)
        {
            return targetInvocationException.InnerException != null ? new ReturnMessage(targetInvocationException.InnerException, methodCall) : new ReturnMessage(targetInvocationException, methodCall);
        }
        catch (Exception exception)
        {
            return new ReturnMessage(exception, methodCall);
        }
        finally
        {
            if (channel as IClientChannel != null)
            {
                try
                {
                    (channel as IClientChannel).Close(TimeSpan.FromSeconds(5));
                }
                catch
                {
                    try
                    {
                        (channel as IClientChannel).Abort();
                    }
                    catch
                    {
                    }
                }
                try
                {
                    (channel as IClientChannel).Dispose();
                }
                catch
                {
                }
            }

            try
            {
                ((IDisposable)channelFactory).Dispose();
            }
            catch
            {
            }
        }
    }
}

    public static class ClientProxyFactory
{
    public static T CreateProxy<T>() where T : class
    {
        return CreateProxy<T>(ProxyType.PerCallChannel);
    }

    public static T CreateProxy<T>(ProxyType proxyType) where T : class
    {
        return CreateProxy<T>(proxyType, null, null);
    }

    public static T CreateProxy<T>(ProxyType proxyType, Binding binding, EndpointAddress endpointAddress) where T : class
    {
        switch (proxyType)
        {
            case ProxyType.PerCallChannel:
                PerCallDisposeRealProxy<T> proxy = null;
                proxy = binding == null && endpointAddress == null ? new PerCallDisposeRealProxy<T>() : new PerCallDisposeRealProxy<T>(binding, endpointAddress);
                Debug.Assert(proxy != null);
                object transparentProxy = proxy.GetTransparentProxy();
                Debug.Assert(transparentProxy != null);
                Debug.Assert(transparentProxy is T);
                return transparentProxy as T;
            default:
                throw new NotImplementedException("Did not implement proxytype:" + proxyType);
        }
    }
}

    public enum ProxyType
{
    /// <summary>
    /// PerCall indicates a proxy that will create a channel pr. proxy method call and dispose of it before returning.
    /// </summary>
    PerCallChannel
}

И позвоните на сайт (в сервисном агенте или там, где вы хотите позвонить во внешнюю службу:

 INumeralConverterService proxy = ClientProxyFactory.CreateProxy<INumeralConverterService>();
 string result = proxy.DecimalToRoman(i);

Учитывая ServiceContract (и контракты данных), определенные в еще одной сборке, здесь просто:

    [ServiceContract]
public interface INumeralConverterService
{
    [OperationContract]
    Decimal RomanToDecimal(string roman);

    [OperationContract]
    string DecimalToRoman(Decimal @decimal);
}
ответил Casper Leon Nielsen 2 MonEurope/Moscow2013-12-02T16:23:51+04:00Europe/Moscow12bEurope/MoscowMon, 02 Dec 2013 16:23:51 +0400 2013, 16:23:51

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

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132