如何在没有svcutil.exe的情况下创建客户端代理或在wcf中添加服务引用? 我想在编译时创建一个客户端代理。
答案 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");
浏览端点,元数据,合同等。
通过指定端点或,为端点创建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);
}