动态生产配置文件 动态修改WCF客户端配置文件终结点的地址的几种方法
动态修改WCF客户端配置文件终结点的地址的几种方法
由于服务器端的IP地址是变化的 所以客户端在登录前需要修改连接地址
思路一 修改客户端配置文件nfig的<client>节点上<endpoint>的address
处理方法如下 但是这个方法有个缺点 就是即便修改配置文件中的地址后 即便是新创建的客户端代理对象 其address依然是修改前的地址 除非重新启动客户端
方法如下
private void UpdateConfig(string serverIPAddress string serverPort)
{
//Configuration config = ConfigurationManager OpenExeConfiguration(Assembly GetEntryAssembly() Location);
Configuration config = ConfigurationManager OpenExeConfiguration(ConfigurationUserLevel None);
ConfigurationSectionGroup sct = config SectionGroups[ system serviceModel ];
ServiceModelSectionGroup serviceModelSectionGroup = sct as ServiceModelSectionGroup;
ClientSection clientSection = serviceModelSectionGroup Client;
foreach (ChannelEndpointElement item in clientSection Endpoints)
{
string pattern = :// */ ;
string address = item Address ToString();
string replacement = string Format( ://{ }:{ }/ serverIPAddress serverPort);
address = Regex Replace(address pattern replacement);
item Address = new Uri(address);
}
config Save(ConfigurationSaveMode Modified);
ConfigurationManager RefreshSection( system serviceModel );
}
至于是否有办法可以刷新这个地址 答案是否定的 原因是 Net framework 在客户端启动时就将nfig 读入了 而且后面即便修改了nfig文件 也不会刷新nfig的内容
至于为什么不重新加载 文章【 】说在通常使用时不可能的 如果要刷新nfig的内容 需要知道nfig的内容何时改变了 这可以通过注册 文件改变通知 事件来实现 然而一旦检测到nfig的内容改变 需要通知所有使用了nfig的组件
那么问题就来了 Net framework 如何来知道哪些组件使用了nfig 由于注册机制的缺陷 是不可能做到 进一步说 实现了所有需要读取nfig的组件在 Net framework中注册这个机制 当 Net framework检测到nfig的改变 它将通知每个注册组件nfig已改变 那么组件该现在该如何做呢?
为了让nfig新的改变生效 组件不得不重新启动它自己 这意味着组件需要能够刷新旧的配置 以及那些基于旧的配置的数据和行为 然后读取新的配置 并从新的配置开始刷新
这是不可能的 举个绑定策略的例子 如果旧的绑定策略认为它需要从装配件(assembly)A中获得版本 而新的策略认为它需要从从装配件(assembly)A中获得版本 在装配件(assembly)A的版本 已经加载的情况下 Net framework 无法为新的绑定策略从装配件(assembly)A中获得版本
仅仅只有一小部分的配置数据可以刷新 这些包括无状态影响或是影响很容易被消除的配置数据 缓存大小就是一个好的例子 在缓存大小改变上 你能重新设置缓存大小 数据仍然保存著 或者简单移除旧的缓存并开启一个新的缓存块
通常来说 当nfig发生改变时 确保所有组件一致性的方法是重启应用程序 这个方法 Net framework所采用的
ASP Net有内置的关于nfig发生改变的检测机制 它在监控nfig上发生的改变 一旦它检测到改变 它将关闭旧的应用程序重新启动新的应用程序
因此 Net framework将来也不会提供配置数据刷新的特征 如果你认为这个对于你很重要 你必须自己去实现这个
幸运的是企业库( Enterprise Library )那帮人理解了这个需求 他们在最新的企业库版本中开发了个 应用程序配置块 (Configuration Application Block)
思路二 如何在不重新启动客户端的情况下改变服务器端的地址 总共有两大类 各有两种情况
第一大类 对于使用代理类
两种情况
( )不使用身份验证
( )使用身份验证
/// <summary>
/// 调用方案一
/// </summary>
/// <param name= serverAddress >服务器地址</param>
private static void CallFirstScheme(string serverAddress)
{
/*
Console WriteLine( 方案一 );
// 测试连接(不使用身份验证)
Console WriteLine( 创建代理对象 userNamePwdValidator );
EndpointAddress address = new EndpointAddress( net tcp:// + serverAddress + : /UserNamePwdValidator/UserNamePwdValidatorService );
UserNamePwdValidatorClient userNamePwdValidator
= new UserNamePwdValidatorClient( UserNamePwdValidatorService address);
bool result = userNamePwdValidator Validate(string Empty string Empty);
Console WriteLine( 测试连接成功 );
// 验证用户名和密码(与测试连接调用同样的接口 不使用身份验证)
//bool result = userNamePwdValidator Validate( admin admin);
// 调用服务(使用身份验证)
Console WriteLine( 创建服务代理对象 user );
UserClient user = new UserClient( UserService );
user Endpoint Address = new EndpointAddress(new Uri( net tcp:// + serverAddress + : /User )
user Endpoint Address Identity user Endpoint Address Headers);
user ClientCredentials UserName UserName = admin ;
user ClientCredentials UserName Password = admin ;
user Insert();
Console WriteLine( 调用服务成功 /n );
}
第二大类 对于使用工厂类
两种情况
( )不使用身份验证
( )使用身份验证
/// <summary>
/// 调用方案二
/// </summary>
/// <param name= serverAddress >服务器地址</param>
private static void CallSecondScheme(string serverAddress)

{
Console WriteLine( 方案二 );
// 测试连接(不使用身份验证)
Console WriteLine( 创建接口对象 userNamePwdValidator );
ChannelFactory<WCFContracts IUserNamePwdValidator> channelFactory
= new ChannelFactory<WCFContracts IUserNamePwdValidator>( Another_UserNamePwdValidatorService );
channelFactory Endpoint Address = new EndpointAddress( net tcp:// + serverAddress + : /UserNamePwdValidator/UserNamePwdValidatorService );
WCFContracts IUserNamePwdValidator otherUserNamePwdValidator = channelFactory CreateChannel();
bool result = otherUserNamePwdValidator Validate(string Empty string Empty);
Console WriteLine( 测试连接成功 );
// 验证用户名和密码(与测试连接调用同样的接口 不使用身份验证)
//bool result = userNamePwdValidator Validate( admin admin);
// 调用服务
Console WriteLine( 创建接口对象 user );
ChannelFactory<WCFContracts IUser> otherChannelFactory = new ChannelFactory<WCFContracts IUser>( Another_UserService );
otherChannelFactory Credentials UserName UserName = admin ;
otherChannelFactory Credentials UserName Password = admin ;
otherChannelFactory Endpoint Address = new EndpointAddress(new Uri( net tcp:// + serverAddress + : /User )
otherChannelFactory Endpoint Address Identity otherChannelFactory Endpoint Address Headers);
WCFContracts IUser otherUser = otherChannelFactory CreateChannel();
otherUser Insert();
Console WriteLine( 调用服务成功 /n );
}
附带身份验证
在VS工具的命令行中
( )添加证书
makecert sr LocalMachine ss My a sha n CN=MyWCFServer sky exchange pe
( )将证书设置成可信任的
lishixinzhi/Article/program/net/201311/13011