如何在没有svcutil的情况下创建客户端代理或在wcf中添加服务引用?

时间:2009-07-06 11:56:47

标签: wcf

如何在没有svcutil.exe的情况下创建客户端代理或在wcf中添加服务引用? 我想在编译时创建一个客户端代理。

4 个答案:

答案 0 :(得分:11)

如果您可以在单独的DLL中访问服务合同(IService接口),则可以添加对该服务合同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();

然后您拥有以编程方式创建的代理,您现在可以根据需要使用它。

答案 1 :(得分:7)

这可能不是你想要的,但它非常有趣。

Vipul Modi有一个库,允许您在下载WSDL之后调用WCF服务,所有这些都在运行时完成。

Vipul Modi's library (latest version)

允许您执行此类操作:

创建指定服务的WSDL URI的ProxyFactory。

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

浏览端点,元数据,合同等。

  • factory.Endpoints
  • factory.Metadata
  • 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();

答案 2 :(得分:5)

您不需要编码生成(或使用完整WCF细节的配置文件)。

首先创建定义服务([ServiceContract])的接口,其中包含与服务实现分开的程序集中的任何支持数据协定。

引用客户端程序集中的接口程序集。

然后需要为IMyService

创建客户端代理
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpoint = new EndpointAddress(url);
ChannelFactory<IMyService> chanFac = new ChannelFactory<IMyService>(binding, endpoint);
IMyService clientProxy = chanFac.CreateChannel();

答案 3 :(得分: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(和datacontracts)在另一个asssembly中定义,这里简单地说:

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

    [OperationContract]
    string DecimalToRoman(Decimal @decimal);
}