WCF 配置 - 将其从 app.config 中拆分出来

Posted

技术标签:

【中文标题】WCF 配置 - 将其从 app.config 中拆分出来【英文标题】:WCF Configuration - Split it out of app.config 【发布时间】:2010-10-03 17:27:46 【问题描述】:

我有一个特定要求,即从主 app.config 文件中删除所有客户端 WCF 配置 (),并将其放入单独的 XML 文件中。我希望看到的行为类似于使用 File="" 指令的 appSettings 部分中可用的行为。事实上,理想情况下,我希望能够为每个使用的服务指定一个单独的文件...

我知道我可以构建一个自定义 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?

C#调用WCF问题汇总

.NET - 部署 WCF 客户端,没有 app.config

如何在生产中配置 WCF 客户端?