我有一个特定的要求,即从主app.config文件中删除所有客户端WCF配置(< system.serviceModel>),并将其删除到单独的XML文件中。我希望看到的行为类似于使用File =“”指令在appSettings部分中提供的行为。事实上,我希望能够为每个消费的服务指定一个单独的文件......
我知道我可以构建一个自定义的ChannelBuilder工厂,它从XML文件(或其中一系列文件)中读取配置数据,但我更愿意仍然让客户端“自动发现”配置数据。
一些基本的Google搜索似乎暗示这是不可能的,但我想从SO中获取视图 - 这里有人知道我无法找到的内容吗? :)
编辑::
Tim Scott和davogones都提出了一个可能的建议,但是依赖于将system.serviceModel部分的组件部分拆分为单独的文件。虽然这不是我想要的(我想分别定义每个服务及其相关元素,每个服务一个文件),但 是一个选项。我会调查并让你知道我的想法。
答案 0 :(得分:17)
您可以使用configSource分离出您的WCF配置。说明:
另一种选择是以编程方式配置WCF服务。
答案 1 :(得分:6)
using System;
using System.Configuration;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Configuration;
namespace ConsoleHost
{
public class CustomServiceHost : ServiceHost
{
public CustomServiceHost(string customConfigPath, Type serviceType,
params Uri[] baseAddresses)
{
CustomConfigPath = customConfigPath;
var collection = new UriSchemeKeyedCollection(baseAddresses);
InitializeDescription(serviceType, collection);
}
public string CustomConfigPath { get; private set; }
protected override void ApplyConfiguration()
{
if (string.IsNullOrEmpty(CustomConfigPath) ||
!File.Exists(CustomConfigPath))
{
base.ApplyConfiguration();
}
else
{
LoadConfigFromCustomLocation(CustomConfigPath);
}
}
void LoadConfigFromCustomLocation(string configFilename)
{
var filemap = new ExeConfigurationFileMap
{
ExeConfigFilename = configFilename
};
Configuration config = ConfigurationManager.
OpenMappedExeConfiguration(filemap, ConfigurationUserLevel.None);
var serviceModel = ServiceModelSectionGroup.GetSectionGroup(config);
bool loaded = false;
foreach (ServiceElement se in serviceModel.Services.Services)
{
if (se.Name == Description.ConfigurationName)
{
LoadConfigurationSection(se);
loaded = true;
break;
}
}
if (!loaded)
throw new ArgumentException("ServiceElement doesn't exist");
}
}
}
在此课程之后使用它,就像您通常用它来初始化服务主机一样
myServiceHost = new CustomServiceHost(ConfigFileName,typeof(QueryTree));
myServiceHost.Open();
答案 2 :(得分:5)
我倾向于以编程方式配置我的所有服务设置。
我的客户并不是理解XML的类型,并且让我让配置文件更像旧的INI风格。
这很容易做到(不包括INI文件代码):
// create the URI which is used as the service endpoint
Uri tcpBaseAddress = new Uri(
string.Format("net.tcp://{0}:{1}",
LocalIPAddress.ToString(), GeneralPortNumber));
// create the net.tcp binding for the service endpoint
NetTcpBinding ntcBinding = new NetTcpBinding();
ntcBinding.Security.Mode = SecurityMode.None;
System.ServiceModel.Channels.Binding tcpBinding = ntcBinding;
// create the service host and add the endpoint
Host = new ServiceHost(typeof(WordWarService), tcpBaseAddress);
由于我们可以以编程方式配置主机(和客户端),因此没有任何东西阻止您以您选择的任何方式提供设置(数据库,xml,疯狂文本文件等)。
答案 3 :(得分:3)
我发现这篇文章可能会帮到你。我没试过,但看起来相当简单。
” configSource属性首先在.NET framework 2.0中引入,以支持外部配置文件。可以将此属性添加到任何配置节,以指定该节的外部文件。
不幸的是,system.serviceModel节组不支持此属性。如果您尝试添加它,您将收到以下异常:
无法指定属性'configSource',因为其名称以保留前缀'config'或'lock'开头
我发现您可以在system.serviceModel下的不同部分使用此属性,例如服务,行为或绑定。 “
答案 4 :(得分:2)
我一直渴望这样做 - 基本上甚至更进一步:将我的WCF配置放在数据库表中(因为我可以更改它 - 无法访问托管提供程序上的文件系统来更改配置文件: - (+)
。不幸的是,这似乎不太简单.....
基本上,它归结为必须编写自己的自定义“ServiceHost”后代,它可以根据需要处理配置。
以下是loading WCF configuration from a custom config location的示例。
这可能会让你走?我仍然希望有一天我能够弄清楚“从数据库表中加载我的配置”.....只需要在工作中安静一周,我猜: - )
答案 5 :(得分:1)
System.ServiceModel.Configuration.ConfigurationChannelFactory
等支持从System.Configuration.Configuration
实例读取配置。这意味着您可以将<system.servicemodel ...
内容放在专用文件中,而无需从web / app.config引用它。您可以拥有多个配置文件,每个客户端一个。
SharePoint 2010在其服务应用程序模型中过度使用了该模型,其中每个服务代理都从专用的.config中读取其设置,该配置不一定是web.config或app.config,甚至不会从那里引用。
答案 6 :(得分:0)
我的工作应用程序有点像你在这里谈论的那样。我们在多个项目中有多个WCF服务,所有配置信息都驻留在一个配置文件中。
我公司选择的解决方案是从配置文件中读取服务配置,然后根据读取的值以编程方式设置绑定,行为等。配置文件中的值不符合您在WCF服务中通常看到的配置内容 - 它被设计为帮助程序类可以在运行时轻松使用所有配置。
所有这一切,我根本不是这样做的忠实粉丝 - 过多的耦合正在发生并且它非常混乱。
但它确实表明它是可能的 - 在你的设计中考虑一件事。
答案 7 :(得分:0)
你可以这样做:
<system.serviceModel configSource="wcf.config"/>
只需剪切您的服务模型部分并将其放在单独的文件中。您必须将整个部分放入单独的配置文件中;使用此方法,您不能让一个部分跨越多个文件AFAIK。