Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
.net WCF配置-将其从app.config中拆分_.net_Wcf_Configuration_App Config - Fatal编程技术网

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

.net WCF配置-将其从app.config中拆分,.net,wcf,configuration,app-config,.net,Wcf,Configuration,App Config,我有一个特定的要求,即从主app.config文件中删除所有客户端WCF配置(),并将其放入一个单独的XML文件中。我希望看到的行为类似于使用File=”“指令在appSettings部分中提供的行为。事实上,我希望能够为每个使用的服务指定一个单独的文件 我知道我可以构建一个定制的ChannelBuilder工厂,从XML文件(或一系列XML文件)中读取配置数据,但我还是希望客户端“自动发现”配置数据 一些基本的谷歌搜索似乎表明这是不可能的,但我想从SO那里获得视图-这里有人知道我找不到的东西吗

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

我知道我可以构建一个定制的ChannelBuilder工厂,从XML文件(或一系列XML文件)中读取配置数据,但我还是希望客户端“自动发现”配置数据

一些基本的谷歌搜索似乎表明这是不可能的,但我想从SO那里获得视图-这里有人知道我找不到的东西吗?:)

编辑::

Tim Scott和davogones都提出了一个可能的建议,但其中一个建议依赖于将system.serviceModel部分的组件部分拆分为单独的文件。虽然这不是我想要的(我想离散地定义每个服务及其相关元素,每个服务一个文件),但它是一个选项。我会调查并让你知道我的想法


我在工作中有一个应用程序,它的工作原理有点像你在这里所说的。我们在多个项目中有多个WCF服务,它们的所有配置信息都驻留在一个配置文件中

我的公司选择的解决方案是从配置文件中读取服务配置,然后根据读取的值以编程方式设置绑定、行为等。配置文件中的值与您通常在WCF服务中看到的配置内容不一致—它被设计为便于助手类在运行时执行所有配置

尽管如此,我一点也不喜欢这样做——太多的耦合正在进行,而且非常混乱


不过,它确实表明了这是可能的——这是设计中需要考虑的一件事。

我一直渴望做同样的事情——基本上更进一步:将我的WCF配置放在数据库表中(因为我可以更改它——无法访问托管提供商上的文件系统来更改配置文件:-())

不幸的是,这似乎不那么简单

基本上,它归结为必须编写自己的自定义“ServiceHost”子代,以便根据需要处理配置

下面是一个例子


这可能会让你走吗?我仍然希望有一天我能想出“从数据库表加载我的配置”的方法……我想,只是需要在工作中安静一周:-)

我倾向于通过编程配置我的所有服务设置

我的客户不是真正理解XML的类型,他们要求我使配置文件更像旧的INI样式

这很容易做到(不包括读取INI文件代码):

由于我们可以通过编程方式配置主机(以及客户端),因此您可以选择任何方式(数据库、xml、疯狂文本文件等)提供设置。

您可以这样做:

<system.serviceModel configSource="wcf.config"/>


只需将您的服务模型部分剪切出来,并将其放在一个单独的文件中。您必须将整个部分放入单独的配置文件中;使用此方法,您不能让一个节跨越多个文件。

您可以使用configSource分离WCF配置。此处的说明:


另一个选择是以编程方式配置WCF服务。

我发现这篇文章可能对您有所帮助。我没有试过,但它似乎相当简单

" configSource属性首先在.NET framework 2.0中引入,以支持外部配置文件。此属性可以添加到任何配置节中,以指定该节的外部文件

很遗憾,system.serviceModel节组不支持此属性。如果尝试添加此属性,您将收到以下异常:

无法指定属性“configSource”,因为其名称以保留前缀“config”或“lock”开头

我发现您可以在system.serviceModel下的不同部分(如服务、行为或绑定)上使用此属性。

System.ServiceModel.Configuration.ConfigurationChannelFactory
等都支持从
System.Configuration.Configuration
实例读取配置。这意味着您可以将

在这个类之后,只需像通常使用它初始化服务主机一样使用它

myServiceHost=新的CustomServiceHost(ConfigFileName,typeof(QueryTree))


myServiceHost.Open()

当然-这适用于您现在拥有的特定设置-但是如果您使用代码配置WCF服务,您确实会失去WCF的一些灵活性,能够在XML配置中定义和配置端点等,而不是使用代码。上面唯一硬编码的是TCP绑定。你可以很容易地从另一个来源读取所有其他数据,这就是我所做的。实际上,原则上我不喜欢WCF XML配置。大量的样板文件、不可理解的选项和非常冗长的语法。让我用Intellisense编写代码,我不必学习新的格式,一切都很好。我仍然可以将端口号之类的内容委托给自定义设置,如@SailingJudo提示::-)你确定??我认为这是行不通的——据我所知,app.config/web.config中的所有元素上都没有定义“configSource”属性……这是行不通的。只能在节上使用configSource,而不能在节组上使用configSource。这仅适用于system.serviceModel的子节(例如绑定、客户端等)。它对system.serviceModel本身不起作用。是的,但这确实足够好吗?请参阅re:“不那么简单。”定制ServiceHost代码可用,或多或少是boilerplate.check System.Serv
<system.serviceModel configSource="wcf.config"/>
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");
        }
    }
}