A little background:
一点背景:
I'm creating a set of adapters to allow communication with mobile devices over different cellular networks. This will be achieved using a class factory pattern. At least one of the networks requires a service reference to communicate with their devices through a web service.
我正在创建一组适配器,以允许通过不同的蜂窝网络与移动设备进行通信。这将使用类工厂模式实现。至少一个网络需要服务引用以通过web服务与其设备通信。
So far I've got 3 assemblies so far which represent:
到目前为止,我到目前为止已经有3个组件代表:
- An assembly which contains the main adapter library: this contains
- The interface definition for each of the adapters
- Base classes
- The class factory to instantiate the specified adapter at runtime.
每个适配器的接口定义
类工厂在运行时实例化指定的适配器。
- An assembly for each network adapter implementation.
- An assembly that contains my main application.
包含主适配器库的程序集:this包含每个适配器的接口定义基类类工厂在运行时实例化指定的适配器。
每个网络适配器实现的程序集。
包含我的主应用程序的程序集。
Given that I don't want to be adding service references and their configuration to the main application assembly [as that's not relevant to the main application], how do I force each assembly's service reference to get its configuration from its own app.config?
鉴于我不想将服务引用及其配置添加到主应用程序程序集[因为它与主应用程序无关],如何强制每个程序集的服务引用从其自己的app.config获取其配置?
If I have the service reference configuration in the main app.config, everything works just fine, but if I move the configuration to the adapter's app.config everything stops working throwing the following exception at the point where I new up the Soap1Client.
如果我在主app.config中有服务引用配置,一切正常,但是如果我将配置移动到适配器的app.config,一切都停止工作,在我新建Soap1Client的时候抛出以下异常。
"Could not find default endpoint element that references contract 'MobileService.Service1Soap' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element."
“无法在ServiceModel客户端配置部分找到引用合同'MobileService.Service1Soap'的默认端点元素。这可能是因为没有为您的应用程序找到配置文件,或者因为在客户端元素中找不到与此合同匹配的端点元素“。
4 个解决方案
#1
In the end, I just removed the service reference and added a web reference [i.e. did it the 2.0 way]. For some reason the web reference will access its own app.config instead of the main application's app.config.
最后,我刚刚删除了服务引用并添加了一个Web引用[即做到2.0的方式]。由于某种原因,Web引用将访问其自己的app.config而不是主应用程序的app.config。
Far easier than the alternative...
比替代方案容易得多......
#2
You can set all the options programatically.
您可以以编程方式设置所有选项。
#3
I don't believe there is a built in .NET way to accomplish this. However you should be able to accomplish it by writing some code to parse each referenced assembly's .config file.
我不相信有一种内置的.NET方法来实现这一目标。但是,您应该能够通过编写一些代码来解析每个引用的程序集的.config文件来完成它。
Here is a sample using assembly specific configuration files that should point you in the right direction: http://www.bearcanyon.com/dotnet/#AssemblySettings.
以下是使用程序集特定配置文件的示例,该文件应指向正确的方向:http://www.bearcanyon.com/dotnet/#AssemblySettings。
I've done something similar in a .NET Winforms app and it worked out well.
我在.NET Winforms应用程序中做了类似的事情并且运行良好。
#4
If you must have the library read the configuration for the service from a config file, then you might be out of luck. The library becomes part of the process and the process uses the configuration of the application that initiated the process.
如果您必须让库从配置文件中读取服务的配置,那么您可能会运气不好。该库成为该过程的一部分,该过程使用启动该过程的应用程序的配置。
However, in your library you could use one of the service reference proxy class constructor overloads to dynamically set the configuration when you instantiate the service reference. Then you don't have to have the service reference binding configuration in any config file. The overload I use takes two parameters: System.ServiceModel.Channels.Binding binding & System.ServiceModel.EndpointAddress remoteAddress. Note that the Binding class is a abstract class, you have to use one of the classes that inherit from it - you can find a list of them here: https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding(v=vs.110).aspx.
但是,在库中,您可以使用服务引用代理类构造函数重载之一在实例化服务引用时动态设置配置。然后,您不必在任何配置文件中具有服务引用绑定配置。我使用的重载有两个参数:System.ServiceModel.Channels.Binding binding和System.ServiceModel.EndpointAddress remoteAddress。请注意,Binding类是一个抽象类,您必须使用从其继承的类之一 - 您可以在此处找到它们的列表:https://msdn.microsoft.com/en-us/library/system。 servicemodel.channels.binding(v = vs.110)的.aspx。
For a simple http service reference I use a default instance of the BasicHttpBinding class and create an instance of the EndpointAddress class using the URL of the service I'm referencing. Obviously you would have to modify this to use https or secured services, etc.
对于简单的http服务引用,我使用BasicHttpBinding类的默认实例,并使用我引用的服务的URL创建EndpointAddress类的实例。显然你必须修改它以使用https或安全服务等。
Of course this still begs the question of how does the library get the correct service URL if you don't want to hard code it in the library? A couple of ways would be to read it from a database or a known file location.
当然,如果您不想在库中对其进行硬编码,这仍然会引发如何获取正确的服务URL的问题?有两种方法可以从数据库或已知文件位置读取它。
#1
In the end, I just removed the service reference and added a web reference [i.e. did it the 2.0 way]. For some reason the web reference will access its own app.config instead of the main application's app.config.
最后,我刚刚删除了服务引用并添加了一个Web引用[即做到2.0的方式]。由于某种原因,Web引用将访问其自己的app.config而不是主应用程序的app.config。
Far easier than the alternative...
比替代方案容易得多......
#2
You can set all the options programatically.
您可以以编程方式设置所有选项。
#3
I don't believe there is a built in .NET way to accomplish this. However you should be able to accomplish it by writing some code to parse each referenced assembly's .config file.
我不相信有一种内置的.NET方法来实现这一目标。但是,您应该能够通过编写一些代码来解析每个引用的程序集的.config文件来完成它。
Here is a sample using assembly specific configuration files that should point you in the right direction: http://www.bearcanyon.com/dotnet/#AssemblySettings.
以下是使用程序集特定配置文件的示例,该文件应指向正确的方向:http://www.bearcanyon.com/dotnet/#AssemblySettings。
I've done something similar in a .NET Winforms app and it worked out well.
我在.NET Winforms应用程序中做了类似的事情并且运行良好。
#4
If you must have the library read the configuration for the service from a config file, then you might be out of luck. The library becomes part of the process and the process uses the configuration of the application that initiated the process.
如果您必须让库从配置文件中读取服务的配置,那么您可能会运气不好。该库成为该过程的一部分,该过程使用启动该过程的应用程序的配置。
However, in your library you could use one of the service reference proxy class constructor overloads to dynamically set the configuration when you instantiate the service reference. Then you don't have to have the service reference binding configuration in any config file. The overload I use takes two parameters: System.ServiceModel.Channels.Binding binding & System.ServiceModel.EndpointAddress remoteAddress. Note that the Binding class is a abstract class, you have to use one of the classes that inherit from it - you can find a list of them here: https://msdn.microsoft.com/en-us/library/system.servicemodel.channels.binding(v=vs.110).aspx.
但是,在库中,您可以使用服务引用代理类构造函数重载之一在实例化服务引用时动态设置配置。然后,您不必在任何配置文件中具有服务引用绑定配置。我使用的重载有两个参数:System.ServiceModel.Channels.Binding binding和System.ServiceModel.EndpointAddress remoteAddress。请注意,Binding类是一个抽象类,您必须使用从其继承的类之一 - 您可以在此处找到它们的列表:https://msdn.microsoft.com/en-us/library/system。 servicemodel.channels.binding(v = vs.110)的.aspx。
For a simple http service reference I use a default instance of the BasicHttpBinding class and create an instance of the EndpointAddress class using the URL of the service I'm referencing. Obviously you would have to modify this to use https or secured services, etc.
对于简单的http服务引用,我使用BasicHttpBinding类的默认实例,并使用我引用的服务的URL创建EndpointAddress类的实例。显然你必须修改它以使用https或安全服务等。
Of course this still begs the question of how does the library get the correct service URL if you don't want to hard code it in the library? A couple of ways would be to read it from a database or a known file location.
当然,如果您不想在库中对其进行硬编码,这仍然会引发如何获取正确的服务URL的问题?有两种方法可以从数据库或已知文件位置读取它。