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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/482835/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 11:05:53  来源:igfitidea点击:

WCF Configuration - Split it out of app.config

.netwcfconfigurationapp-config

提问by ZombieSheep

I have a specific requirement to remove all client WCF configuration (<system.serviceModel>) out of the main app.config file, and into a separate XML file. The behaviour I would like to see is similar to that available in the appSettings section using the File="" directive. In fact, I'd ideally like to be able to specify a separate file for each consumed service...

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

I know I can build a custom ChannelBuilder factory that reads config data from an XML file (or a series of them), but I would prefer to still have the config data "auto-discovered" by the client.

我知道我可以构建一个自定义 ChannelBuilder 工厂,它从 XML 文件(或一系列文件)中读取配置数据,但我更愿意让客户端“自动发现”配置数据。

Some basic Google searches seem to suggest this is not possible, but I wanted to get the view from SO - does anyone here know something I haven't been able to find? :)

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

Edit ::

Tim Scott and davogones both came up with a possible suggestion, but one which relies on splitting the component sections of the system.serviceModel section out to separate files. Although this isn't quite what I'm looking for (I'd like to define each service and its associated elements discretely, one file per service), it isan option. I'll investigate and let you know what I thought.

编辑 ::

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

采纳答案by Sailing Judo

I have a tendency to programatically configure all my service settings.

我倾向于以编程方式配置我的所有服务设置。

My clients aren't really the type to understand XML and have asked me make configuration files more like the old INI style.

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

This is easy to do (reading INI file code not included):

这很容易做到(不包括读取 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);

Since we can configure the host (and client, for that matter) programatically there is nothing keeping you from supplying the settings in any manner you choose (database, xml, crazy text file, etc).

由于我们可以以编程方式配置主机(和客户端),因此没有什么可以阻止您以您选择的任何方式(数据库、xml、疯狂的文本文件等)提供设置。

回答by davogones

You can separate out your WCF configuration using configSource. Instructions here:

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

http://weblogs.asp.net/cibrax/archive/2007/07/24/configsource-attribute-on-system-servicemodel-section.aspx

http://weblogs.asp.net/cibrax/archive/2007/07/24/configsource-attribute-on-system-servicemodel-section.aspx

Another option is to configure your WCF services programatically.

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

回答by Samir

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");
        }
    }
}

After this class just use it as you would normally use it to initialize the service host

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

myServiceHost = new CustomServiceHost(ConfigFileName, typeof(QueryTree));

myServiceHost = new CustomServiceHost(ConfigFileName, typeof(QueryTree));

myServiceHost.Open();

myServiceHost.Open();

回答by Boris

I found this article that may help you out. I have not tried it, but it seems fairly straightforward.

我发现这篇文章可以帮助你。我还没有尝试过,但它似乎相当简单。

http://weblogs.asp.net/cibrax/archive/2007/07/24/configsource-attribute-on-system-servicemodel-section.aspx

http://weblogs.asp.net/cibrax/archive/2007/07/24/configsource-attribute-on-system-servicemodel-section.aspx

" The configSource attribute was firstly introduced in .NET framework 2.0 to support external configuration files. This attribute can be added to any configuration section to specify an external file for that section.

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

Unfortunately, the system.serviceModel section group does not support this attribute. If you try to add it, you will receive the following exception:

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

The attribute 'configSource' cannot be specified because its name starts with the reserved prefix 'config' or 'lock'

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

What I found out is that you can use this attribute on the different sections under system.serviceModel such as services, behaviors or bindings. "

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

回答by marc_s

I've been longing to do the same - basically even one step further: put my WCF config in a database table (since I can change that - can't access the file system on my hosted provider to change config files :-().

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

Unfortunately, this seems less than simple.....

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

Basically, it boils down to having to write your own custom "ServiceHost" descendant which can handle the configuration as needed.

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

Here's an example of loading WCF configuration from a custom config location.

下面是从自定义配置位置加载 WCF 配置的示例。

This might get you going? I'm still hoping I'll be able to figure out the "loading my config from a database table" some day..... just need to quiet week at work, I guess :-)

这可能会让你前进?我仍然希望有一天我能够弄清楚“从数据库表加载我的配置”.....只需要在工作中安静一周,我猜:-)

回答by marc_s

System.ServiceModel.Configuration.ConfigurationChannelFactoryet al support reading the configuration from a System.Configuration.Configurationinstance. Which means you can put the <system.servicemodel ...stuff in a dedicated file without referencing it from web/app.config. You could have multiple config files, one for each client.

System.ServiceModel.Configuration.ConfigurationChannelFactory等人支持从System.Configuration.Configuration实例读取配置。这意味着您可以将这些<system.servicemodel ...内容放在一个专用文件中,而无需从 web/app.config 中引用它。您可以有多个配置文件,每个客户端一个。

SharePoint 2010 uses that excessively in its service application model, where each service proxy reads its settings from a dedicated .config which is not necessarily web.config or app.config and isn't even referenced from there.

SharePoint 2010 在其服务应用程序模型中过度使用它,其中每个服务代理从专用 .config 读取其设置,该 .config 不一定是 web.config 或 app.config,甚至没有从那里引用。

回答by Tim Scott

You can do like this:

你可以这样做:

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

Just cut your service model section out and put it in a separate file. You will have to put the whole section into the separate config file; using this method you cannot have a section span multiple files AFAIK.

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

回答by Tad Donaghe

I have an application at work that works kind of like what you're talking about here. We have multiple WCF services across multiple projects and all of their configuration information resides in a single config file.

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

The solution my company chose was to read the service configuration out of the config file and then programmatically set up the bindings, behavior, etc based on the values read. The values in the config file don't conform to the config stuff you usually see in WCF services - it was designed to be easily used by a helper class to do all the configuration at run time.

我公司选择的解决方案是从配置文件中读取服务配置,然后根据读取的值以编程方式设置绑定、行为等。配置文件中的值不符合您通常在 WCF 服务中看到的配置内容 - 它被设计为帮助程序类在运行时轻松使用它来完成所有配置。

All that said, I'm not a big fan of doing that at all - too much coupling going on and it's pretty messy.

综上所述,我根本不喜欢这样做——耦合太多,而且非常混乱。

It does, though, show that it's possible - it's one thing to think about in your design.

但是,它确实表明这是可能的 - 在您的设计中考虑一件事。