通用 WCF 代理实现
Generic WCF proxy implementation
我正在编写一个代理来访问 WCF 服务,我们可以在其中访问 WCF 服务和客户端代码。
对于服务契约接口中的每个方法,我正在编写一个这样的方法。
麻烦的是界面中有很多方法,实际上这变成了复制和粘贴练习。
是否有更优雅的方式(使用 lambda 表达式?)不那么冗长?我无法快速弄清楚....
public interface IServiceContract
{
DataContracts.TypeA Method1(int arg1, string arg2);
string Method2(string arg1);
DateTime Method3();
int Method4(DataContracts.Input1);
// etc............
}
public class Proxy : IServiceContract....
public DataContracts.TypeA Method1(int arg1, string arg2)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return proxy.Method1(arg1, arg2);
}
finally
{
CloseConnection(proxy, factory);
}
}
public List<AnOtherResultPoco> Method2(string arg1)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return proxy.Method2(args1);
}
finally
{
CloseConnection(proxy, factory);
}
}
//ad inifinitum for methods,3,4,5...
你可以使用反射。
public List<MyResultType> SearchBy(string searchTerm, string method)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
if (!IsMethodAllowed(method))
{
throw new SecurityException();
}
return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, new object[] { searchTerm });
}
finally
{
CloseConnection(proxy, factory);
}
}
这是另一种方式,也许是您正在寻找的。
public List<MyResultType> SearchByMethod1(int a, int b)
{
return (List<MyResultType>)SearchBy(new object[] { a, b }, "Method1");
}
public List<MyResultType2> SearchByMethod2(MyResultType b)
{
return (List<MyResultType2>)SearchBy(new object[] { b }, "Method1");
}
protected object SearchBy(object[] parameters, string method)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
if (!IsMethodAllowed(method))
{
throw new SecurityException();
}
return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, parameters);
}
finally
{
CloseConnection(proxy, factory);
}
}
这不会导致您的代码中到处都是泛型。它被整齐地包裹在代理里面。
如果您想使用 lambda 对代码进行一些因式分解,我建议编写如下所示的方法:
...
public void ServiceCall(Action<IFileService> action)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return action(proxy);
}
finally
{
CloseConnection(proxy, factory);
}
}
所以你这样调用你的服务方法:
...
List<AnOtherResultPoco> result;
MyClass.ServiceCall(p => { result = p.Method2("hello"); });
...
我知道这是一个老问题,但我今天 运行 遇到了同样的问题,并找到了一个简单的解决方案,我想我会与未来的用户分享。
所以在这个解决方案中,我们将创建自己的代理而不是生成服务引用。
这是代理,想法是让它通用:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
}
技巧来了:
对于 void 方法:
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
对于return:
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
其中 TResult 是 returning 类型。
使用方法:
Proxy<IService> proxy = new Proxy();
// for a void method
Proxy.Execute(prxy => prxy.Method());
// for non void method.
var result = Proxy.Execute(prxy => prxy.Method());
所以,总而言之,代理 class 应该是这样的:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
}
我推荐此解决方案用于自定义 wcf 代理,无需使用任何服务引用,它非常简单易行。
我正在编写一个代理来访问 WCF 服务,我们可以在其中访问 WCF 服务和客户端代码。
对于服务契约接口中的每个方法,我正在编写一个这样的方法。
麻烦的是界面中有很多方法,实际上这变成了复制和粘贴练习。
是否有更优雅的方式(使用 lambda 表达式?)不那么冗长?我无法快速弄清楚....
public interface IServiceContract
{
DataContracts.TypeA Method1(int arg1, string arg2);
string Method2(string arg1);
DateTime Method3();
int Method4(DataContracts.Input1);
// etc............
}
public class Proxy : IServiceContract....
public DataContracts.TypeA Method1(int arg1, string arg2)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return proxy.Method1(arg1, arg2);
}
finally
{
CloseConnection(proxy, factory);
}
}
public List<AnOtherResultPoco> Method2(string arg1)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return proxy.Method2(args1);
}
finally
{
CloseConnection(proxy, factory);
}
}
//ad inifinitum for methods,3,4,5...
你可以使用反射。
public List<MyResultType> SearchBy(string searchTerm, string method)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
if (!IsMethodAllowed(method))
{
throw new SecurityException();
}
return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, new object[] { searchTerm });
}
finally
{
CloseConnection(proxy, factory);
}
}
这是另一种方式,也许是您正在寻找的。
public List<MyResultType> SearchByMethod1(int a, int b)
{
return (List<MyResultType>)SearchBy(new object[] { a, b }, "Method1");
}
public List<MyResultType2> SearchByMethod2(MyResultType b)
{
return (List<MyResultType2>)SearchBy(new object[] { b }, "Method1");
}
protected object SearchBy(object[] parameters, string method)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
if (!IsMethodAllowed(method))
{
throw new SecurityException();
}
return (List<MyResultType>)proxy.GetType().GetMethod(method).Invoke(proxy, parameters);
}
finally
{
CloseConnection(proxy, factory);
}
}
这不会导致您的代码中到处都是泛型。它被整齐地包裹在代理里面。
如果您想使用 lambda 对代码进行一些因式分解,我建议编写如下所示的方法:
...
public void ServiceCall(Action<IFileService> action)
{
IFileService proxy = null;
ChannelFactory<IFileService> factory = null;
try
{
factory = new ChannelFactory<IFileService>("*");
proxy = factory.CreateChannel();
return action(proxy);
}
finally
{
CloseConnection(proxy, factory);
}
}
所以你这样调用你的服务方法:
...
List<AnOtherResultPoco> result;
MyClass.ServiceCall(p => { result = p.Method2("hello"); });
...
我知道这是一个老问题,但我今天 运行 遇到了同样的问题,并找到了一个简单的解决方案,我想我会与未来的用户分享。 所以在这个解决方案中,我们将创建自己的代理而不是生成服务引用。
这是代理,想法是让它通用:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
}
技巧来了:
对于 void 方法:
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
对于return:
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
其中 TResult 是 returning 类型。
使用方法:
Proxy<IService> proxy = new Proxy();
// for a void method
Proxy.Execute(prxy => prxy.Method());
// for non void method.
var result = Proxy.Execute(prxy => prxy.Method());
所以,总而言之,代理 class 应该是这样的:
public class Proxy<T>
{
public ChannelFactory<T> Channel { get; set; }
public Proxy()
{
Channel = new ChannelFactory<T>("endpoint");
}
public T CreateChannel()
{
return Channel.CreateChannel();
}
public void Execute(Action<T> action)
{
T proxy = CreateChannel();
action(proxy);
((ICommunicationObject)proxy).Close();
}
public TResult Execute<TResult>(Func<T, TResult> function)
{
T proxy = CreateChannel();
var result = function(proxy);
((ICommunicationObject)proxy).Close();
return result;
}
}
我推荐此解决方案用于自定义 wcf 代理,无需使用任何服务引用,它非常简单易行。