WCF 配置 - 将其从 app.config 中拆分出来
Posted
技术标签:
【中文标题】WCF 配置 - 将其从 app.config 中拆分出来【英文标题】:WCF Configuration - Split it out of app.config 【发布时间】:2010-10-03 17:27:46 【问题描述】:我有一个特定要求,即从主 app.config 文件中删除所有客户端 WCF 配置 (
我知道我可以构建一个自定义 ChannelBuilder 工厂,它从 XML 文件(或一系列 XML 文件)读取配置数据,但我更希望客户端“自动发现”配置数据。
一些基本的谷歌搜索似乎表明这是不可能的,但我想从 SO 那里得到视图 - 这里有人知道我找不到的东西吗? :)
编辑 ::
Tim Scott 和 davogones 都提出了一个可能的建议,但它依赖于将 system.serviceModel 部分的组件部分拆分为单独的文件。虽然这不是我想要的(我想离散地定义每个服务及其关联元素,每个服务一个文件),它是一个选项。我会调查并告诉你我的想法。
【问题讨论】:
检查 System.ServiceModel.Configuration.ConfigurationChannelFactory 警告:一旦你这样做了,你就会失去智能感知,这在 .NET 4 中得到了极大的改进,甚至可以解析你的绑定并告诉你丢失的东西 【参考方案1】: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】:我一直渴望做同样的事情 - 基本上更进一步:将我的 WCF 配置放入数据库表中(因为我可以更改它 - 无法访问我的托管提供商上的文件系统来更改配置文件: -()。
不幸的是,这似乎并不简单.....
基本上,归结为必须编写您自己的自定义“ServiceHost”后代,它可以根据需要处理配置。
这是loading WCF configuration from a custom config location 的示例。
这可能会让你继续前进吗?我仍然希望有一天我能够弄清楚“从数据库表中加载我的配置”......我想只需要安静一周的工作即可:-)
【讨论】:
回复:“不那么简单。”自定义 ServiceHost 代码可用,或多或少是样板。【参考方案3】:System.ServiceModel.Configuration.ConfigurationChannelFactory
等支持从System.Configuration.Configuration
实例读取配置。这意味着您可以将<system.servicemodel ...
的内容放在一个专用文件中,而无需从 web/app.config 中引用它。您可以有多个配置文件,每个客户端一个。
SharePoint 2010 在其服务应用程序模型中过度使用它,其中每个服务代理从专用的 .config 读取其设置,该 .config 不一定是 web.config 或 app.config,甚至没有从那里引用。
【讨论】:
将不胜感激提供有关如何提供此功能的文档。 同意。这个答案太模糊,没有用。【参考方案4】:我发现这篇文章可能会对您有所帮助。我没有尝试过,但它看起来相当简单。
http://weblogs.asp.net/cibrax/archive/2007/07/24/configsource-attribute-on-system-servicemodel-section.aspx
" configSource 属性首先在 .NET Framework 2.0 中引入,用于支持外部配置文件。可以将此属性添加到任何配置部分以指定该部分的外部文件。
很遗憾,system.serviceModel 节组不支持此属性。如果您尝试添加它,您将收到以下异常:
无法指定属性“configSource”,因为它的名称以保留前缀“config”或“lock”开头
我发现你可以在 system.serviceModel 下的不同部分使用这个属性,例如服务、行为或绑定。 "
【讨论】:
【参考方案5】:您可以使用 configSource 分离出您的 WCF 配置。这里的说明:
http://weblogs.asp.net/cibrax/archive/2007/07/24/configsource-attribute-on-system-servicemodel-section.aspx
另一种选择是以编程方式配置 WCF 服务。
【讨论】:
【参考方案6】:你可以这样做:
<system.serviceModel configSource="wcf.config"/>
只需删除您的服务模型部分并将其放入单独的文件中。您必须将整个部分放入单独的配置文件中;使用这种方法,你不能让一个部分跨越多个文件 AFAIK。
【讨论】:
你确定吗??我认为这行不通——据我所知,app.config/web.config 中的所有元素都没有定义“configSource”属性.... 这不起作用。您只能在 section 上使用 configSource,而不是 sectionGroups。 这仅适用于 system.serviceModel 的子部分(例如绑定、客户端等)。它不适用于 system.serviceModel 本身。 是的——但这肯定足够好了吗? weblogs.asp.net/cibrax/archive/2007/07/24/… 见***.com/questions/858225/…【参考方案7】:我倾向于以编程方式配置我的所有服务设置。
我的客户不是真正理解 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、疯狂的文本文件等)提供设置。
【讨论】:
当然——这适用于你现在的特定设置——但是如果你在代码中配置你的 WCF 服务,你确实失去了 WCF 的一些灵活性,能够仅在 XML 配置中定义和配置端点等,insteda of code。 上面唯一硬编码的是 TCP 绑定。您可以轻松地从其他来源读取所有其他数据,这就是我所做的。 为此 +1。原则上我实际上不喜欢 WCF XML 配置。大量样板文件、难以理解的选项和非常冗长的语法。让我用 Intellisense 编写代码,我不必学习新格式,一切都很好。正如@SailingJudo 提示的那样,我仍然可以将诸如端口号之类的事情委托给自定义设置。 :-)【参考方案8】:我有一个正在工作的应用程序,它的工作方式与您在此处所说的类似。我们在多个项目中有多个 WCF 服务,它们的所有配置信息都驻留在一个配置文件中。
我公司选择的解决方案是从配置文件中读取服务配置,然后根据读取的值以编程方式设置绑定、行为等。配置文件中的值不符合您通常在 WCF 服务中看到的配置内容 - 它旨在方便帮助类在运行时进行所有配置。
话虽如此,我一点也不喜欢这样做 - 耦合太多,而且非常混乱。
不过,它确实表明这是可能的 - 这是您的设计中需要考虑的一件事。
【讨论】:
以上是关于WCF 配置 - 将其从 app.config 中拆分出来的主要内容,如果未能解决你的问题,请参考以下文章
WCF C# - 从 App.config 获取特定的配置值
如果 DLL 的 app.config 应该在“主配置”中……我们如何处理 DLL 中的 WCF 引用?
WCF 何时使用 app.config 或 web.config?