16

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

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

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

编辑 ::

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

4

8 回答 8

17

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

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

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

于 2009-01-28T07:37:44.283 回答
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();

于 2010-12-31T11:45:45.680 回答
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、疯狂的文本文件等)提供设置。

于 2009-01-27T19:29:02.273 回答
3

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

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 下的不同部分使用此属性,例如服务、行为或绑定。"

于 2010-06-25T12:55:09.913 回答
2

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

不幸的是,这似乎并不简单......

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

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

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

于 2009-01-27T18:18:15.927 回答
1

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

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

于 2010-06-25T13:13:47.513 回答
0

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

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

尽管如此,我根本不喜欢这样做——太多的耦合发生了,而且很混乱。

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

于 2009-01-27T16:47:31.397 回答
0

你可以这样做:

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

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

于 2009-01-27T22:26:36.500 回答