先画个图 。
其中:
1) WcfRequest,WcfResponse,IWcfService 组成契约的基本
2) WcfServiceBase为实现契约部分也就是 wcf服务
3) WcfClient为契约的使用方,也就是wcf客户端
WCF 通用契约定义用于所有交互的调用的基接口。
其中WcfRequest和WcfResponse 作为输入输出参数的封装
[ServiceContract]
public interface IWcfService
{
[OperationContract]
WcfResponse Request(WcfRequest req);
}
为了通用其中返回参数和输入参数多用object, 后面具体的实现时使用WCF特性用于限定范围
如: 需要具体类型的定义时可使用 ServiceKnownTypeAttribute 来进行定义
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(UserEntity))]
public interface IWcfHello : IWcfService
{
}
但这样用起来不是太方便,可参考 MSDN 官网的例子 , 用一个外部类进行类型集合的整理
业务契约定义
[ServiceContract]
[ServiceKnownType("GetKnownTypes", typeof(Helper))]
public interface IWcfService
{
}
Helper类定义 及方法GetKnownTypes
static class Helper
{
public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)
{
System.Collections.Generic.List<System.Type> knownTypes =
new System.Collections.Generic.List<System.Type>();
knownTypes.Add(typeof(UserEntity));
//knownTypes.Add(...);
return knownTypes;
}
}
wcf 客户端有多种使用方法,其中.net使用,微软提供了类ClientBase, 只要实现此类就能方便使用 , 在这里加上自定义的泛型约束,可限制此类的使用范围
加入 两个方法, 分别于用调用有返回和没有返回的方法。
/// <summary>
/// wcf客户端基类
/// </summary>
/// <typeparam name="TChannel">基于IWcfService的类型</typeparam>
public abstract class WcfClient<TChannel> : ClientBase<TChannel>, IDisposable
where TChannel : class, IWcfService
{
/// <summary>
/// 默认的wcf绑定参数
/// </summary>
protected static NetTcpBinding wcfBinding;
static WcfClient()
{
wcfBinding = new NetTcpBinding();
wcfBinding.Security.Mode = SecurityMode.None;
}
/// <summary>
/// 用户指定的wcf绑定配置
/// </summary>
protected Binding binding;
/// <summary>
/// wcf连接地址
/// </summary>
protected EndpointAddress remoteAddress;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="edpAddr">连接地址</param>
protected WcfClient(EndpointAddress edpAddr)
: base(wcfBinding, edpAddr) { this.binding = wcfBinding; this.remoteAddress = edpAddr; }
/// <summary>
/// 构造函数
/// </summary>
/// <param name="binding">wcf绑定配置</param>
/// <param name="edpAddr">连接地址</param>
protected WcfClient(Binding binding, EndpointAddress edpAddr)
: base(binding, edpAddr) { this.binding = wcfBinding; this.remoteAddress = edpAddr; }
private WcfResponse Request(string methodName, params object[] parameters)
{
WcfRequest req = new WcfRequest();
req.Head.RequestMethodName = methodName;
req.Head.ClassName = this.GetType().Name;
if (parameters != null)
req.Body.Parameters = parameters;
return base.Channel.Request(req);
}
/// <summary>
/// 执行wcf方法并返回数据
/// </summary>
/// <typeparam name="Return">返回类型</typeparam>
/// <param name="methodName">方法名</param>
/// <param name="parameters">参数</param>
/// <returns>返回结果</returns>
protected virtual Return RequestFunc<Return>(string methodName, params object[] parameters)
{
var res = Request( methodName, parameters);
if (res.Head.IsSuccess)
return (Return)res.Body.Data;
// 返回不是真 抛出异常
throw new MyException(res.Head.Message);
}
/// <summary>
/// 执行wcf方法没有返回数据
/// </summary>
/// <param name="methodName">方法名</param>
/// <param name="parameters">参数</param>
protected virtual void RequestAction(string methodName, params object[] parameters)
{
var res = Request(methodName, parameters);
if (res.Head.IsSuccess)
return;
// 返回不是真 抛出异常
throw new MyException(res.Head.Message);
}
}
在使用时可直接继承此类,加入需要使用的业务接口。
业务接口:
public interface IHello
{
string CallHello(UserEntity user);
int Times();
void Reset();
}
客户端调用类
public class WcfClientHello : WcfClient<IWcfHello>, IHello
{
public WcfClientHello(EndpointAddress addr)
: base(addr)
{
}
public string CallHello(UserEntity user)
{
return base.RequestFunc<string>("CallHello", new object[] { user });
}
public int Times()
{
return base.RequestFunc<int>("Times");
}
public void Reset()
{
base.RequestAction("Reset");
}
}
这样外部直接就能这样使用了
var client = new WcfClientHello(addr);
var str = client.CallHello(new UserEntity { Name = "mmx", Age = 132 });
完整的测试代码 点击打开链接